aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore74
-rw-r--r--CMakeLists.txt403
-rw-r--r--README7
-rw-r--r--apps/CMakeLists.txt10
-rwxr-xr-xapps/osmocom_fft974
-rwxr-xr-xapps/osmocom_siggen2
-rwxr-xr-xapps/osmocom_siggen_nogui10
-rwxr-xr-xapps/osmocom_spectrum_sense22
-rw-r--r--cmake/Modules/CMakeParseArgumentsCopy.cmake138
-rw-r--r--cmake/Modules/FindGnuradioFCD.cmake34
-rw-r--r--cmake/Modules/FindGnuradioFCDPP.cmake41
-rw-r--r--cmake/Modules/FindGnuradioIQBalance.cmake29
-rw-r--r--cmake/Modules/FindGnuradioUHD.cmake34
-rw-r--r--cmake/Modules/FindLibAIRSPYHF.cmake24
-rw-r--r--cmake/Modules/FindLibMiriSDR.cmake27
-rw-r--r--cmake/Modules/FindLibOsmoSDR.cmake27
-rw-r--r--cmake/Modules/FindLibXTRX.cmake27
-rw-r--r--cmake/Modules/FindLibbladeRF.cmake4
-rw-r--r--cmake/Modules/GrComponent.cmake115
-rw-r--r--cmake/Modules/GrMiscUtils.cmake519
-rw-r--r--cmake/Modules/GrPlatform.cmake54
-rw-r--r--cmake/Modules/GrPython.cmake242
-rw-r--r--cmake/Modules/GrTest.cmake143
-rw-r--r--cmake/Modules/GrVersion.cmake82
-rw-r--r--cmake/Modules/OsmoSDRMiscUtils.cmake132
-rw-r--r--cmake/Modules/osmosdrConfig.cmake31
-rw-r--r--docs/CMakeLists.txt14
-rw-r--r--docs/doxygen/Doxyfile.in8
-rw-r--r--docs/doxygen/Doxyfile.swig_doc.in2
-rw-r--r--docs/doxygen/other/group_defs.dox4
-rw-r--r--docs/doxygen/other/main_page.dox4
-rw-r--r--gnuradio-osmosdr.pc.in15
-rw-r--r--grc/CMakeLists.txt10
-rw-r--r--grc/gen_osmosdr_blocks.py12
-rw-r--r--include/osmosdr/CMakeLists.txt8
-rw-r--r--include/osmosdr/pimpl.h6
-rw-r--r--lib/CMakeLists.txt193
-rw-r--r--lib/airspy/CMakeLists.txt25
-rw-r--r--lib/airspy/airspy_source_c.cc3
-rw-r--r--lib/airspy/airspy_source_c.h9
-rw-r--r--lib/airspyhf/airspyhf_source_c.cc437
-rw-r--r--lib/arg_helpers.h15
-rw-r--r--lib/bladerf/CMakeLists.txt26
-rw-r--r--lib/bladerf/bladerf_common.cc24
-rw-r--r--lib/bladerf/bladerf_common.h11
-rw-r--r--lib/bladerf/bladerf_compat.h2
-rw-r--r--lib/bladerf/bladerf_sink_c.cc25
-rw-r--r--lib/bladerf/bladerf_source_c.cc14
-rw-r--r--lib/config.h.in4
-rw-r--r--lib/device.cc63
-rw-r--r--lib/fcd/CMakeLists.txt39
-rw-r--r--lib/fcd/fcd_source_c.cc21
-rw-r--r--lib/fcd/fcd_source_c.h13
-rw-r--r--lib/file/CMakeLists.txt25
-rw-r--r--lib/freesrp/CMakeLists.txt23
-rw-r--r--lib/freesrp/freesrp_common.cc3
-rw-r--r--lib/freesrp/freesrp_common.h3
-rw-r--r--lib/gnuradio-osmosdr.rc.in55
-rw-r--r--lib/hackrf/CMakeLists.txt33
-rw-r--r--lib/hackrf/hackrf_common.cc427
-rw-r--r--lib/hackrf/hackrf_common.h113
-rw-r--r--lib/hackrf/hackrf_sink_c.cc425
-rw-r--r--lib/hackrf/hackrf_sink_c.h37
-rw-r--r--lib/hackrf/hackrf_source_c.cc453
-rw-r--r--lib/hackrf/hackrf_source_c.h40
-rw-r--r--lib/miri/CMakeLists.txt (renamed from lib/xtrx/CMakeLists.txt)16
-rw-r--r--lib/miri/miri_source_c.cc451
-rw-r--r--lib/miri/miri_source_c.h (renamed from lib/airspyhf/airspyhf_source_c.h)98
-rw-r--r--lib/osmosdr/CMakeLists.txt (renamed from lib/airspyhf/CMakeLists.txt)28
-rw-r--r--lib/osmosdr/osmosdr_src_c.cc533
-rw-r--r--lib/osmosdr/osmosdr_src_c.h139
-rw-r--r--lib/ranges.cc13
-rw-r--r--lib/redpitaya/CMakeLists.txt23
-rw-r--r--lib/rfspace/CMakeLists.txt20
-rw-r--r--lib/rfspace/rfspace_source_c.cc156
-rw-r--r--lib/rfspace/rfspace_source_c.h31
-rw-r--r--lib/rtl/CMakeLists.txt24
-rw-r--r--lib/rtl/rtl_source_c.cc7
-rw-r--r--lib/rtl/rtl_source_c.h9
-rw-r--r--lib/rtl_tcp/CMakeLists.txt24
-rw-r--r--lib/rtl_tcp/rtl_tcp_source_c.cc10
-rw-r--r--lib/sdrplay/CMakeLists.txt23
-rw-r--r--lib/sdrplay/sdrplay_source_c.h7
-rw-r--r--lib/sink_impl.cc107
-rw-r--r--lib/soapy/CMakeLists.txt23
-rw-r--r--lib/soapy/soapy_common.cc4
-rw-r--r--lib/soapy/soapy_common.h5
-rw-r--r--lib/soapy/soapy_sink_c.cc16
-rw-r--r--lib/soapy/soapy_source_c.cc27
-rw-r--r--lib/source_impl.cc199
-rw-r--r--lib/uhd/CMakeLists.txt26
-rw-r--r--lib/uhd/uhd_sink_c.cc15
-rw-r--r--lib/uhd/uhd_source_c.cc15
-rw-r--r--lib/xtrx/xtrx_obj.cc138
-rw-r--r--lib/xtrx/xtrx_obj.h68
-rw-r--r--lib/xtrx/xtrx_sink_c.cc505
-rw-r--r--lib/xtrx/xtrx_sink_c.h129
-rw-r--r--lib/xtrx/xtrx_source_c.cc583
-rw-r--r--lib/xtrx/xtrx_source_c.h127
-rw-r--r--python/CMakeLists.txt8
-rw-r--r--python/__init__.py13
-rw-r--r--swig/CMakeLists.txt23
102 files changed, 5451 insertions, 4041 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..05e004f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,74 @@
+*~
+*.pyc
+*.pyo
+build*/
+cmake-*
+libosmo-dsp/*
+
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 74c54f5..76375dc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,12 +21,20 @@
# Project setup
########################################################################
cmake_minimum_required(VERSION 3.8)
-include(GNUInstallDirs)
project(gr-osmosdr CXX C)
enable_testing()
-#policy setup
-cmake_policy(SET CMP0011 NEW)
+#install to PyBOMBS target prefix if defined
+if(DEFINED ENV{PYBOMBS_PREFIX})
+ set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX})
+ message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}")
+endif()
+
+# Get GNU Radio Installation Prefix
+if(DEFINED CMAKE_INSTALL_PREFIX)
+ set(GR_PREFIX ${CMAKE_INSTALL_PREFIX})
+ message(STATUS "Installation is located at: ${GR_PREFIX}")
+endif()
#select the release build type by default to get optimization flags
if(NOT CMAKE_BUILD_TYPE)
@@ -35,190 +43,104 @@ if(NOT CMAKE_BUILD_TYPE)
endif(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "")
-########################################################################
-# GNURadio setup
-########################################################################
+#make sure our local CMake Modules path comes first
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules)
-# Find GNURadio (pmt and runtime are core, always included)
-find_package(Gnuradio "3.8" REQUIRED COMPONENTS blocks fft filter)
+set(ENABLE_NONFREE FALSE CACHE BOOL "Enable or disable nonfree components.")
# Set the version information here
-set(VERSION_MAJOR 0)
-set(VERSION_API 2)
-set(VERSION_ABI 0)
-set(VERSION_PATCH 0)
-include(GrVersion) #setup version info
+set(VERSION_INFO_MAJOR_VERSION 0)
+set(VERSION_INFO_API_COMPAT 1)
+set(VERSION_INFO_MINOR_VERSION 5)
+set(VERSION_INFO_MAINT_VERSION git)
+
+cmake_policy(SET CMP0011 NEW)
+
########################################################################
# Compiler specific setup
########################################################################
-
-if((CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR
- CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- AND NOT WIN32)
- #http://gcc.gnu.org/wiki/Visibility
- add_definitions(-fvisibility=hidden)
- add_definitions(-fvisibility-inlines-hidden)
-endif()
-
-if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- set(CMAKE_CXX_STANDARD 11)
-elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CMAKE_CXX_STANDARD 11)
-elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
- set(CMAKE_CXX_STANDARD 11)
-else()
- message(WARNING "C++ standard could not be set because compiler is not GNU, Clang or MSVC.")
-endif()
-
-# Misc options
-if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR
- CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- add_definitions(-Wall)
- add_definitions(-Wextra)
- add_definitions(-Wno-unused-parameter)
- add_definitions(-Wsign-compare)
- #add_definitions(-Wconversion)
- #add_definitions(-pedantic)
- #add_definitions(-ansi)
-endif()
-
-# SIMD
-if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|x86")
- set(USE_SIMD "SSE2" CACHE STRING "Use SIMD instructions")
-else()
- set(USE_SIMD "no" CACHE STRING "Use SIMD instructions")
-endif()
-set(USE_SIMD_VALUES "no" "SSE2" "AVX")
-set_property(CACHE USE_SIMD PROPERTY STRINGS ${USE_SIMD_VALUES})
-list(FIND USE_SIMD_VALUES ${USE_SIMD} USE_SIMD_INDEX)
-if(${USE_SIMD_INDEX} EQUAL -1)
+IF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|x86")
+ SET(USE_SIMD "SSE2" CACHE STRING "Use SIMD instructions")
+ELSE()
+ SET(USE_SIMD "no" CACHE STRING "Use SIMD instructions")
+ENDIF()
+SET(USE_SIMD_VALUES "no" "SSE2" "AVX")
+SET_PROPERTY(CACHE USE_SIMD PROPERTY STRINGS ${USE_SIMD_VALUES})
+LIST(FIND USE_SIMD_VALUES ${USE_SIMD} USE_SIMD_INDEX)
+IF(${USE_SIMD_INDEX} EQUAL -1)
message(FATAL_ERROR "Option ${USE_SIMD} not supported, valid entries are ${USE_SIMD_VALUES}")
-endif()
+ENDIF()
+
+IF(CMAKE_CXX_COMPILER MATCHES ".*clang")
+ SET(CMAKE_COMPILER_IS_CLANGXX 1)
+ENDIF()
+
+IF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
+ ADD_DEFINITIONS(-Wall)
+ ADD_DEFINITIONS(-Wextra)
+ ADD_DEFINITIONS(-Wno-unused-parameter)
+ ADD_DEFINITIONS(-Wsign-compare)
+ #ADD_DEFINITIONS(-Wconversion)
+ #ADD_DEFINITIONS(-pedantic)
+ #ADD_DEFINITIONS(-ansi)
+ IF(NOT WIN32)
+ #only export symbols that are declared to be part of the api (non dll platforms)
+ ADD_DEFINITIONS(-fvisibility=hidden)
+ ADD_DEFINITIONS(-fvisibility-inlines-hidden)
+ ENDIF(NOT WIN32)
+ IF(USE_SIMD MATCHES SSE2)
+ ADD_DEFINITIONS(-msse2)
+ ADD_DEFINITIONS(-DUSE_SSE2)
+ ENDIF()
+ IF(USE_SIMD MATCHES AVX)
+ ADD_DEFINITIONS(-march=native)
+ ADD_DEFINITIONS(-DUSE_AVX)
+ ENDIF()
+ELSEIF(MSVC)
+ IF(USE_SIMD MATCHES SSE2)
+ ADD_DEFINITIONS(/arch:SSE2)
+ ADD_DEFINITIONS(-DUSE_SSE2)
+ ENDIF()
+ IF(USE_SIMD MATCHES AVX)
+ ADD_DEFINITIONS(/arch:AVX)
+ ADD_DEFINITIONS(-DUSE_AVX)
+ ENDIF()
+ENDIF()
-if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR
- CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- if(USE_SIMD MATCHES SSE2)
- add_definitions(-msse2)
- add_definitions(-DUSE_SSE2)
- endif()
- if(USE_SIMD MATCHES AVX)
- add_definitions(-march=native)
- add_definitions(-DUSE_AVX)
- endif()
-elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
- if(USE_SIMD MATCHES SSE2)
- add_definitions(/arch:SSE2)
- add_definitions(-DUSE_SSE2)
- endif()
- if(USE_SIMD MATCHES AVX)
- add_definitions(/arch:AVX)
- add_definitions(-DUSE_AVX)
- endif()
- # boost feels like using lib pragmas to link to libs,
- # but the boost libs might not even be in the (default) lib search path
- add_definitions(-DBOOST_ALL_NO_LIB)
- # macro turns std::min into errors...
- add_definitions(-DNOMINMAX)
-endif()
########################################################################
-# Find boost
+# Install directories
########################################################################
-find_package(Boost "1.65" REQUIRED chrono thread system)
-
-if(NOT Boost_FOUND)
- message(FATAL_ERROR "Boost required to compile osmosdr")
+find_package(Gnuradio REQUIRED) # Side effect of MODULE_PATH getting prepended with system components
+list(REVERSE CMAKE_MODULE_PATH)
+set(MIN_GR_VERSION "3.8")
+if("${Gnuradio_VERSION}" VERSION_LESS MIN_GR_VERSION)
+ MESSAGE(FATAL_ERROR "GnuRadio version required: >=\"" ${MIN_GR_VERSION} "\" found: \"" ${Gnuradio_VERSION} "\"")
endif()
-########################################################################
-# Find build dependencies and setup options
-########################################################################
-
-include(GrComponent)
-
-set(ENABLE_NONFREE FALSE CACHE BOOL "Enable or disable nonfree components.")
-
+include(GrVersion)
- # GNURadio components & OOTs
- ##############################
-
-
- # Note this is not supposed to be lique that for GR components
- # but ATM GR's handling of components is broken
-message(STATUS "Searching for GNURadio-Blocks...")
-find_package(gnuradio-blocks PATHS ${Gnuradio_DIR})
-message(STATUS " Found GNURadio-Blocks: ${gnuradio-blocks_FOUND}")
-
-message(STATUS "Searching for IQ Balance...")
-find_package(gnuradio-iqbalance PATHS ${Gnuradio_DIR})
-message (STATUS " Found IQ Balance: ${gnuradio-iqbalance_FOUND}")
-
-message(STATUS "Searching for UHD Drivers...")
-find_package(UHD)
-message (STATUS " Found UHD Driver: ${UHD_FOUND}")
-
-message(STATUS "Searching for UHD Block...")
-find_package(gnuradio-uhd PATHS ${Gnuradio_DIR})
-message (STATUS " Found UHD Block: ${gnuradio-uhd_FOUND}")
-
-message(STATUS "Searching for Volk...")
-find_package(Volk REQUIRED)
-message (STATUS " Found Volk: ${Volk_FOUND}")
-
- # Hardware drivers
- ####################
-
-find_package(LibRTLSDR)
-if(ENABLE_NONFREE)
- find_package(LibSDRplay)
-endif(ENABLE_NONFREE)
-find_package(LibHackRF)
-find_package(LibAIRSPY)
-find_package(LibAIRSPYHF)
-find_package(LibbladeRF)
-find_package(GnuradioFCDPP)
-find_package(SoapySDR NO_MODULE)
-find_package(LibFreeSRP)
-find_package(LibXTRX)
-find_package(Doxygen)
-
- # Python
- ##########
-
-find_package(PythonLibs 3)
-find_package(SWIG)
-
-if(SWIG_FOUND)
- message(STATUS "Minimum SWIG version required is 1.3.31")
- set(SWIG_VERSION_CHECK FALSE)
- if("${SWIG_VERSION}" VERSION_GREATER "1.3.30")
- set(SWIG_VERSION_CHECK TRUE)
- endif()
-endif(SWIG_FOUND)
-
-GR_REGISTER_COMPONENT("Python support" ENABLE_PYTHON
- PYTHONLIBS_FOUND
- SWIG_FOUND
- SWIG_VERSION_CHECK
-)
-
-########################################################################
-# Install directories
-########################################################################
include(GrPlatform) #define LIB_SUFFIX
-
if(NOT CMAKE_MODULES_DIR)
set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake)
endif(NOT CMAKE_MODULES_DIR)
-set(GR_INCLUDE_DIR include)
set(GR_CMAKE_DIR ${CMAKE_MODULES_DIR}/osmosdr)
+set(GR_RUNTIME_DIR bin)
+set(GR_LIBRARY_DIR lib${LIB_SUFFIX})
+set(GR_INCLUDE_DIR include)
+set(GR_DATA_DIR share)
set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME})
-set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME})
+set(GR_DOC_DIR ${GR_DATA_DIR}/doc)
+if (NOT GR_PKG_DOC_DIR)
+ set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME})
+endif()
+set(GR_CONF_DIR etc)
set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d)
+set(GR_LIBEXEC_DIR libexec)
set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME})
+set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
########################################################################
# On Apple only, set install name and use rpath correctly, if not already set
@@ -241,10 +163,67 @@ if(APPLE)
endif(APPLE)
########################################################################
-# Setup doxygen option
+# Find build dependencies
########################################################################
+set(GR_REQUIRED_COMPONENTS RUNTIME PMT BLOCKS)
+
+find_package(gnuradio-blocks PATHS ${GR_PREFIX}/lib/cmake/gnuradio/)
+message(STATUS "Found Block Block: ${gnuradio-blocks_FOUND}")
+
+#[[find_package(gnuradio-pmt PATHS ${GR_PREFIX}/lib/cmake/gnuradio/)
+message(STATUS "Found PMT Block: ${gnuradio-pmt_FOUND}")
+
+find_package(gnuradio-runtime PATHS ${GR_PREFIX}/lib/cmake/gnuradio/)
+message(STATUS "Found Runtime Block: ${gnuradio-runtime_FOUND}")
+
+# Software Components part of GNU Radio - These should all be present for a default install
+message(STATUS " Searching for IQ Balance...")
+#find_package(Gnuradio COMPONENTS iqbalance REQUIRED)
+find_package(gnuradio-iqbalance PATHS ${GR_PREFIX}/lib/cmake/iqbalance)
+message (STATUS "Found IQ Balance: ${gnuradio-iqbalance_FOUND}")
+
+message(STATUS " Searching for UHD Drivers...")
+#find_package(Gnuradio COMPONENTS uhd REQUIRED)
+find_package(UHD REQUIRED ${GR_PREFIX}/lib/cmake/uhd)
+message (STATUS "Found UHD Driver: ${UHD_FOUND}")
+
+message(STATUS " Searching for UHD Block...")
+#find_package(Gnuradio COMPONENTS gnuradio-uhd REQUIRED)
+find_package(gnuradio-uhd PATHS ${GR_PREFIX}/lib/cmake/gnuradio/)
+message (STATUS "Found UHD Block: ${gnuradio-uhd_FOUND}")
+
+message(STATUS " Searching for Volk...")
+#find_package(Gnuradio COMPONENTS Volk REQUIRED)
+find_package(volk PATHS ${GR_PREFIX}/lib/cmake/volk)
+message (STATUS "Found Volk: ${volk_FOUND}") ]]#
+
+find_package(GnuradioIQBalance)
+find_package(UHD)
+find_package(GnuradioUHD)
+find_package(LibOsmoSDR)
+find_package(LibRTLSDR)
+find_package(LibMiriSDR)
+if(ENABLE_NONFREE)
+ find_package(LibSDRplay)
+endif(ENABLE_NONFREE)
+find_package(LibHackRF)
+find_package(LibAIRSPY)
+find_package(Volk)
+find_package(LibbladeRF)
+find_package(SoapySDR NO_MODULE)
+find_package(LibFreeSRP)
find_package(Doxygen)
+#get_cmake_property(_variableNames VARIABLES)
+#list (SORT _variableNames)
+#foreach (_variableName ${_variableNames})
+# message(STATUS "${_variableName}=${${_variableName}}")
+#endforeach()
+
+
+########################################################################
+# Setup doxygen option
+########################################################################
if(DOXYGEN_FOUND)
option(ENABLE_DOXYGEN "Build docs using Doxygen" ON)
else(DOXYGEN_FOUND)
@@ -252,6 +231,25 @@ else(DOXYGEN_FOUND)
endif(DOXYGEN_FOUND)
########################################################################
+# Setup the include and linker paths
+########################################################################
+include_directories(
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_SOURCE_DIR}/lib
+ ${Boost_INCLUDE_DIRS}
+ ${GNURADIO_ALL_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${Boost_LIBRARY_DIRS}
+ ${GNURADIO_ALL_LIBRARY_DIRS}
+)
+
+# Set component parameters
+set(GR_OSMOSDR_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE)
+set(GR_OSMOSDR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/swig CACHE INTERNAL "" FORCE)
+
+########################################################################
# Create uninstall target
########################################################################
configure_file(
@@ -263,6 +261,29 @@ add_custom_target(uninstall
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
)
+
+########################################################################
+# Enable python component
+########################################################################
+find_package(PythonLibs)
+find_package(SWIG)
+
+if(SWIG_FOUND)
+ message(STATUS "Minimum SWIG version required is 1.3.31")
+ set(SWIG_VERSION_CHECK FALSE)
+ if("${SWIG_VERSION}" VERSION_GREATER "1.3.30")
+ set(SWIG_VERSION_CHECK TRUE)
+ endif()
+endif(SWIG_FOUND)
+
+include(GrComponent)
+GR_REGISTER_COMPONENT("Python support" ENABLE_PYTHON
+ PYTHONLIBS_FOUND
+ SWIG_FOUND
+ SWIG_VERSION_CHECK
+ )
+
+
########################################################################
# Add subdirectories
########################################################################
@@ -277,6 +298,51 @@ endif(ENABLE_PYTHON)
add_subdirectory(docs)
########################################################################
+# Install cmake search helper for this library
+########################################################################
+
+install(FILES cmake/Modules/osmosdrConfig.cmake
+ DESTINATION ${CMAKE_MODULES_DIR}/osmosdr
+)
+
+########################################################################
+# Create Pkg Config File
+########################################################################
+FOREACH(inc ${Boost_INCLUDE_DIRS})
+ LIST(APPEND GR_OSMOSDR_PC_CFLAGS "-I${inc}")
+ENDFOREACH(inc)
+
+FOREACH(lib ${Boost_LIBRARY_DIRS})
+ LIST(APPEND GR_OSMOSDR_PC_LIBS "-L${lib}")
+ENDFOREACH(lib)
+
+# use space-separation format for the pc file
+STRING(REPLACE ";" " " GR_OSMOSDR_PC_REQUIRES "${GR_OSMOSDR_PC_REQUIRES}")
+STRING(REPLACE ";" " " GR_OSMOSDR_PC_CFLAGS "${GR_OSMOSDR_PC_CFLAGS}")
+STRING(REPLACE ";" " " GR_OSMOSDR_PC_LIBS "${GR_OSMOSDR_PC_LIBS}")
+
+# unset these vars to avoid hard-coded paths to cross environment
+IF(CMAKE_CROSSCOMPILING)
+ UNSET(GR_OSMOSDR_PC_CFLAGS)
+ UNSET(GR_OSMOSDR_PC_LIBS)
+ENDIF(CMAKE_CROSSCOMPILING)
+
+# fake gnuradio cpack behavior as long as we don't use it directly
+set(CPACK_PACKAGE_NAME "gnuradio-osmosdr")
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "GNU Radio block for various radio hardware")
+set(CPACK_PACKAGE_VERSION ${VERSION})
+
+CONFIGURE_FILE(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-osmosdr.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-osmosdr.pc
+ @ONLY)
+
+INSTALL(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-osmosdr.pc
+ DESTINATION ${GR_LIBRARY_DIR}/pkgconfig
+)
+
+########################################################################
# Print Summary
########################################################################
GR_PRINT_COMPONENT_SUMMARY()
@@ -284,7 +350,8 @@ if(ENABLE_NONFREE)
MESSAGE(STATUS
"NONFREE components have been enabled. The resulting
binaries cannot be distributed under GPL terms.
- ")
+ "
+ )
endif(ENABLE_NONFREE)
MESSAGE(STATUS "Building for version: ${VERSION} / ${LIBVER}")
diff --git a/README b/README
index 6550b3d..4d8363b 100644
--- a/README
+++ b/README
@@ -1,10 +1,10 @@
While primarily being developed for the OsmoSDR hardware, this block
as well supports:
- * FUNcube Dongle through libgnuradio-fcd
- * FUNcube Dongle Pro+ through gr-fcdproplus
+ * sysmocom OsmoSDR Devices through libosmosdr
* RTL2832U based DVB-T dongles through librtlsdr
* RTL-TCP spectrum server (see librtlsdr project)
+ * MSi2500 based DVB-T dongles through libmirisdr
* SDRplay RSP through SDRplay API library
* gnuradio .cfile input through libgnuradio-blocks
* RFSPACE SDR-IQ, SDR-IP, NetSDR (incl. X2 option)
@@ -13,8 +13,7 @@ as well supports:
* Great Scott Gadgets HackRF through libhackrf
* Nuand LLC bladeRF through libbladeRF library
* Ettus USRP Devices through Ettus UHD library
- * Fairwaves UmTRX through Fairwaves' module for UHD
- * Fairwaves XTRX through libxtrx
+ * Fairwaves UmTRX through Fairwaves' fork of UHD
* Red Pitaya SDR transceiver (http://bazaar.redpitaya.com)
* FreeSRP through libfreesrp
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 2b9e0c9..9c30a4b 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2011 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -28,7 +28,7 @@ GR_PYTHON_INSTALL(
GR_PYTHON_INSTALL(
PROGRAMS
osmocom_fft
- # osmocom_siggen
+ osmocom_siggen
osmocom_siggen_nogui
osmocom_spectrum_sense
DESTINATION ${GR_RUNTIME_DIR}
diff --git a/apps/osmocom_fft b/apps/osmocom_fft
index 10a682c..da38861 100755
--- a/apps/osmocom_fft
+++ b/apps/osmocom_fft
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
#
# Copyright 2012 Free Software Foundation, Inc.
#
@@ -20,71 +20,45 @@
# Boston, MA 02110-1301, USA.
#
+SAMP_RANGE_KEY = 'samp_range'
+SAMP_RATE_KEY = 'samp_rate'
+GAIN_KEY = lambda x: 'gain:'+x
+BWIDTH_KEY = 'bwidth'
+CENTER_FREQ_KEY = 'center_freq'
+FREQ_CORR_KEY = 'freq_corr'
+FREQ_RANGE_KEY = 'freq_range'
+GAIN_RANGE_KEY = lambda x: 'gain_range:'+x
+BWIDTH_RANGE_KEY = 'bwidth_range'
+
import osmosdr
from gnuradio import blocks
-from gnuradio import gr
+from gnuradio import gr, gru
from gnuradio import eng_notation
-from gnuradio.filter import firdes
+from gnuradio.gr.pubsub import pubsub
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-from functools import partial
import sys
-import signal
+import numpy
import time
import datetime
try:
- from PyQt5 import Qt
- from gnuradio import qtgui
- import sip
- from gnuradio.qtgui import Range, RangeWidget
+ from gnuradio.wxgui import stdgui2, form, slider
+ from gnuradio.wxgui import forms
+ from gnuradio.wxgui import fftsink2, waterfallsink2, scopesink2
+ import wx
except ImportError:
- sys.stderr.write("Error importing GNU Radio's Qtgui.\n")
+ sys.stderr.write("Error importing GNU Radio's wxgui. Please make sure gr-wxgui is installed.\n")
sys.exit(1)
+class app_top_block(stdgui2.std_top_block, pubsub):
+ def __init__(self, frame, panel, vbox, argv):
+ stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)
+ pubsub.__init__(self)
-class CallEvent(Qt.QEvent):
- """An event containing a request for a function call."""
- EVENT_TYPE = Qt.QEvent.Type(Qt.QEvent.registerEventType())
-
- def __init__(self, fn, *args, **kwargs):
- Qt.QEvent.__init__(self, self.EVENT_TYPE)
- self.fn = fn
- self.args = args
- self.kwargs = kwargs
-
-
-class freq_recv(gr.sync_block, Qt.QObject):
- def __init__(self, callback):
- gr.sync_block.__init__(self, name="freq_recv", in_sig=None, out_sig=None)
- Qt.QObject.__init__(self)
-
- self.set_freq=callback
-
- # Advertise 'msg' port
- self.message_port_register_in(gr.pmt.intern('msg'))
- self.set_msg_handler(gr.pmt.intern('msg'), self.handle_msg)
-
- def handle_msg(self, msg_pmt):
- # Unpack message & call set_freq on main thread
- meta = gr.pmt.to_python(gr.pmt.car(msg_pmt))
- msg = gr.pmt.cdr(msg_pmt)
- if meta=="freq":
- freq = gr.pmt.to_double(msg)
- Qt.QCoreApplication.postEvent(self, CallEvent(self.set_freq, freq))
-
- def event(self, event):
- event.accept()
- result = event.fn(*event.args, **event.kwargs)
- return True
-
-
-class app_top_block(gr.top_block, Qt.QMainWindow):
- def __init__(self, argv, title):
- gr.top_block.__init__(self, title)
- Qt.QMainWindow.__init__(self)
- self.setWindowTitle(title)
+ self.frame = frame
+ self.panel = panel
parser = OptionParser(option_class=eng_option)
parser.add_option("-a", "--args", type="string", default="",
@@ -115,8 +89,6 @@ class app_top_block(gr.top_block, Qt.QMainWindow):
help="Enable fosphor display")
parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
help="Enable oscilloscope display")
- parser.add_option("-Q", "--qtgui", action="store_true", default=False,
- help="Enable QTgui 'all-in-one' display")
parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1,
help="Set fftsink averaging factor, default=[%default]")
parser.add_option("", "--averaging", action="store_true", default=False,
@@ -140,20 +112,16 @@ class app_top_block(gr.top_block, Qt.QMainWindow):
self._verbose = options.verbose
- try:
- self.src = osmosdr.source(options.args)
- except RuntimeError:
- print("Couldn't instanciate source (no device present?).", file=sys.stderr)
- sys.exit(1)
+ self.src = osmosdr.source(options.args)
try:
self.src.get_sample_rates().start()
except RuntimeError:
- print("Source has no sample rates (wrong device arguments?).", file=sys.stderr)
+ print "Source has no sample rates (wrong device arguments?)."
sys.exit(1)
# Set the antenna
- if options.antenna:
+ if(options.antenna):
self.src.set_antenna(options.antenna)
# Set the clock source:
@@ -172,6 +140,7 @@ class app_top_block(gr.top_block, Qt.QMainWindow):
options.gain = float(r.start()+r.stop())/2
except RuntimeError:
options.gain = 0
+ pass
else:
options.gain = gain
@@ -180,28 +149,19 @@ class app_top_block(gr.top_block, Qt.QMainWindow):
if self._verbose:
gain_names = self.src.get_gain_names()
for name in gain_names:
- rg = self.src.get_gain_range(name)
- print("%s gain range: start %g stop %g step %g" % (name, rg.start(), rg.stop(), rg.step()))
+ range = self.src.get_gain_range(name)
+ print "%s gain range: start %d stop %d step %d" % (name, range.start(), range.stop(), range.step())
if options.gains:
for tuple in options.gains.split(","):
name, gain = tuple.split(":")
gain = int(gain)
- print("Setting gain %s to %g." % (name, gain))
+ print "Setting gain %s to %d." % (name, gain)
self.src.set_gain(gain, name)
if self._verbose:
rates = self.src.get_sample_rates()
- print('Supported sample rates %.10g-%.10g step %.10g.' % (rates.start(), rates.stop(), rates.step()))
-
- self.bandwidth_ok = True
- try:
- rg = self.src.get_bandwidth_range()
- range_start = rg.start()
- if self._verbose:
- print('Supported bandwidth rates %.10g-%.10g step %.10g.' % (rg.start(), rg.stop(), rg.step()))
- except RuntimeError as ex:
- self.bandwidth_ok = False
+ print 'Supported sample rates %d-%d step %d.' % (rates.start(), rates.stop(), rates.step())
if options.center_freq is None:
freq = self.src.get_center_freq()
@@ -211,99 +171,93 @@ class app_top_block(gr.top_block, Qt.QMainWindow):
# if no freq was specified, use the mid-point in Hz
r = self.src.get_freq_range()
options.center_freq = float(r.start()+r.stop())/2
- if self._verbose:
- print("Using auto-calculated mid-point frequency")
input_rate = self.src.set_sample_rate(options.samp_rate)
self.src.set_bandwidth(input_rate)
- if self._verbose:
- ranges = self.src.get_freq_range()
- print("Supported frequencies %s-%s"%(eng_notation.num_to_str(ranges.start()), eng_notation.num_to_str(ranges.stop())))
+ self.publish(SAMP_RANGE_KEY, self.src.get_sample_rates)
+ self.publish(FREQ_RANGE_KEY, self.src.get_freq_range)
+ for name in self.get_gain_names():
+ self.publish(GAIN_RANGE_KEY(name), (lambda self=self,name=name: self.src.get_gain_range(name)))
- for name in self.src.get_gain_names():
- print("GAIN(%s): %g"%(name, self.src.get_gain(name)))
+ self.publish(BWIDTH_RANGE_KEY, self.src.get_bandwidth_range)
+
+ for name in self.get_gain_names():
+ self.publish(GAIN_KEY(name), (lambda self=self,name=name: self.src.get_gain(name)))
+
+ self.publish(BWIDTH_KEY, self.src.get_bandwidth)
# initialize values from options
- if options.freq_corr is not None:
- self.set_freq_corr(options.freq_corr)
+ self[SAMP_RANGE_KEY] = self.src.get_sample_rates()
+ self[SAMP_RATE_KEY] = options.samp_rate
+ self[CENTER_FREQ_KEY] = options.center_freq
+ self[FREQ_CORR_KEY] = options.freq_corr
+ self['record'] = options.record
self.dc_offset_mode = options.dc_offset_mode
self.iq_balance_mode = options.iq_balance_mode
# initialize reasonable defaults for DC / IQ correction
- self.dc_offset_real = 0
- self.dc_offset_imag = 0
- self.iq_balance_mag = 0
- self.iq_balance_pha = 0
+ self['dc_offset_real'] = 0
+ self['dc_offset_imag'] = 0
+ self['iq_balance_mag'] = 0
+ self['iq_balance_pha'] = 0
+
+ #subscribe set methods
+ self.subscribe(SAMP_RATE_KEY, self.set_sample_rate)
+
+ for name in self.get_gain_names():
+ self.subscribe(GAIN_KEY(name), (lambda gain,self=self,name=name: self.set_named_gain(gain, name)))
+
+ self.subscribe(BWIDTH_KEY, self.set_bandwidth)
+ self.subscribe(CENTER_FREQ_KEY, self.set_freq)
+ self.subscribe(FREQ_CORR_KEY, self.set_freq_corr)
+
+ self.subscribe('dc_offset_real', self.set_dc_offset)
+ self.subscribe('dc_offset_imag', self.set_dc_offset)
+ self.subscribe('iq_balance_mag', self.set_iq_balance)
+ self.subscribe('iq_balance_pha', self.set_iq_balance)
+
+ #force update on pubsub keys
+ #for key in (SAMP_RATE_KEY, BWIDTH_KEY, CENTER_FREQ_KEY, FREQ_CORR_KEY):
+ #print key, "=", self[key]
+ #self[key] = self[key]
if options.fosphor:
from gnuradio import fosphor
- self.scope = fosphor.qt_sink_c()
- self.scope.set_frequency_range(0, input_rate)
- self.scope_win = sip.wrapinstance(self.scope.pyqwidget(), Qt.QWidget)
- self.scope_win.setMinimumSize(800, 300)
+ self.scope = fosphor.wx_sink_c(panel, size=(800,300))
+ self.scope.set_sample_rate(input_rate)
+ self.frame.SetMinSize((800,600))
elif options.waterfall:
- self.scope = qtgui.waterfall_sink_c(
- options.fft_size,
- wintype=firdes.WIN_BLACKMAN_hARRIS,
- fc=0,
- bw=input_rate,
- name="",
- nconnections=1
- )
- self.scope.enable_grid(False)
- self.scope.enable_axis_labels(True)
- self.scope.set_intensity_range(-100, 20)
- self.scope_win = sip.wrapinstance(self.scope.pyqwidget(), Qt.QWidget)
- self.scope_win.setMinimumSize(800, 420)
-
+ self.scope = waterfallsink2.waterfall_sink_c (panel,
+ fft_size=options.fft_size,
+ sample_rate=input_rate,
+ ref_scale=options.ref_scale,
+ ref_level=20.0,
+ y_divs = 12)
+
+ self.scope.set_callback(self.wxsink_callback)
+ self.frame.SetMinSize((800, 420))
elif options.oscilloscope:
- self.scope = qtgui.time_sink_c(
- options.fft_size,
- samp_rate=input_rate,
- name="",
- nconnections=1
- )
- self.scope_win = sip.wrapinstance(self.scope.pyqwidget(), Qt.QWidget)
- self.scope_win.setMinimumSize(800, 600)
-
- elif options.qtgui:
- self.scope = qtgui.sink_c(
- options.fft_size,
- wintype=firdes.WIN_BLACKMAN_hARRIS,
- fc=0,
- bw=input_rate,
- name="",
- plotfreq=True,
- plotwaterfall=True,
- plottime=True,
- plotconst=True
- )
- self.scope_win = sip.wrapinstance(self.scope.pyqwidget(), Qt.QWidget)
- self.scope.set_update_time(1.0/10)
- self.scope_win.setMinimumSize(800, 600)
-
+ self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate)
+ self.frame.SetMinSize((800, 600))
else:
- self.scope = qtgui.freq_sink_c(
- fftsize=options.fft_size,
- wintype=firdes.WIN_BLACKMAN_hARRIS,
- fc=0,
- bw=input_rate,
- name="",
- nconnections=1
- )
- self.scope_win = sip.wrapinstance(self.scope.pyqwidget(), Qt.QWidget)
- self.scope.disable_legend()
- self.scope_win.setMinimumSize(800, 420)
-
- self.connect((self.src, 0), (self.scope, 0))
- try:
- self.freq = freq_recv(self.set_freq)
- self.msg_connect((self.scope, 'freq'), (self.freq, 'msg'))
- except RuntimeError:
- self.freq = None
+ self.scope = fftsink2.fft_sink_c (panel,
+ fft_size=options.fft_size,
+ sample_rate=input_rate,
+ ref_scale=options.ref_scale,
+ ref_level=20.0,
+ y_divs = 12,
+ average=options.averaging,
+ peak_hold=options.peak_hold,
+ avg_alpha=options.avg_alpha,
+ fft_rate=options.fft_rate)
+
+ self.scope.set_callback(self.wxsink_callback)
+ self.frame.SetMinSize((800, 420))
+
+ self.connect(self.src, self.scope)
self.file_sink = blocks.file_sink(gr.sizeof_gr_complex, "/dev/null", False)
self.file_sink.set_unbuffered(False)
@@ -311,404 +265,586 @@ class app_top_block(gr.top_block, Qt.QMainWindow):
# lock/connect/unlock at record button event did not work, so we leave it connected at all times
self.connect(self.src, self.file_sink)
- self._build_gui()
+ self._build_gui(vbox)
+
+ if self.dc_offset_mode != None:
+ self.set_dc_offset_mode(self.dc_offset_mode)
+
+ if self.iq_balance_mode != None:
+ self.set_iq_balance_mode(self.iq_balance_mode)
# set initial values
- if not self.set_freq(options.center_freq):
+ if not(self.set_freq(options.center_freq)):
self._set_status_msg("Failed to set initial frequency")
- if options.record is not None:
- self._fre.insert(options.record)
def record_to_filename(self):
- s = self._fre.text()
+ s = self['record']
s = s.replace('%S', '%e' % self.src.get_sample_rate())
s = s.replace('%F', '%e' % self.src.get_center_freq())
s = s.replace('%T', datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
return s
- def _set_status_msg(self, msg, timeout=0):
- self.status.showMessage(msg, timeout)
+ def wxsink_callback(self, x, y):
+ self.set_freq_from_callback(x)
- def _shrink(self, widget):
- """Try to shrink RangeWidget by removing unnecessary margins"""
- try:
- widget.layout().setContentsMargins(0, 0, 0, 0)
- widget.children()[0].layout().setContentsMargins(0, 0, 0, 0)
- except:
- pass
+ def _set_status_msg(self, msg):
+ self.frame.GetStatusBar().SetStatusText(msg, 0)
- def _add_section(self, text, layout):
- """Add a section header to the GUI"""
- frame = Qt.QWidget()
- frame_layout = Qt.QHBoxLayout()
- frame_layout.setContentsMargins(0, 0, 0, 0)
- frame.setLayout(frame_layout)
-
- wid = Qt.QLabel()
- wid.setText(text)
- wid.setStyleSheet("font-weight: bold;")
- frame_layout.addWidget(wid)
- wid = Qt.QFrame()
- wid.setFrameShape(Qt.QFrame.HLine)
- frame_layout.addWidget(wid)
- frame_layout.setStretchFactor(wid, 1)
-
- layout.addWidget(frame)
-
- def _chooser(self, names, callback, default=0):
- """A simple radio-button chooser"""
- buttons = Qt.QWidget()
- blayout = Qt.QHBoxLayout()
- bgroup = Qt.QButtonGroup()
- buttons.setObjectName("foo")
- buttons.setStyleSheet("QWidget#foo {border: 1px outset grey;}")
- buttons.setLayout(blayout)
- chooser = []
- for (num, txt) in enumerate(names):
- rb = Qt.QRadioButton(txt)
- rb.clicked.connect(partial(callback, num))
- chooser.append(rb)
- bgroup.addButton(rb,num)
- blayout.addWidget(rb)
- if num == default:
- rb.setChecked(True)
- return buttons
-
- def _build_gui(self):
-
- self.top_widget = Qt.QWidget()
-
- self.top_layout = Qt.QVBoxLayout(self.top_widget)
- self.top_layout.addWidget(self.scope_win)
-
- self.setCentralWidget(self.top_widget)
-
- self.status = Qt.QStatusBar()
- self.setStatusBar(self.status)
- self.status.setStyleSheet("QStatusBar{border-top: 1px outset grey;}")
-
- if hasattr(RangeWidget, 'EngSlider'):
- eng_widget="eng_slider"
- else:
- eng_widget="counter_slider"
+ def _build_gui(self, vbox):
+
+ if hasattr(self.scope, 'win'):
+ vbox.Add(self.scope.win, 1, wx.EXPAND)
+ vbox.AddSpacer(3)
+
+ # add control area at the bottom
+ self.myform = myform = form.form()
##################################################
# Frequency controls
##################################################
- self._add_section("Frequency", self.top_layout)
+ fc_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Center Frequency",
+ orient=wx.VERTICAL,
+ bold=True)
+ fc_vbox.AddSpacer(3)
+ # First row of frequency controls (center frequency)
+ freq_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ fc_vbox.Add(freq_hbox, 0, wx.EXPAND)
+ fc_vbox.AddSpacer(5)
+ # Second row of frequency controls (freq. correction)
+ corr_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ fc_vbox.Add(corr_hbox, 0, wx.EXPAND)
+ fc_vbox.AddSpacer(3)
+
+ # Add frequency controls to top window sizer
+ vbox.Add(fc_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(5)
+
+ freq_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=freq_hbox,
+ label='Center Frequency (Hz)',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=CENTER_FREQ_KEY,
+ )
+ freq_hbox.AddSpacer(5)
+
+ try: # range.start() == range.stop() in file= mode
+
+ forms.slider(
+ parent=self.panel, sizer=freq_hbox,
+ proportion=3,
+ ps=self,
+ key=CENTER_FREQ_KEY,
+ minimum=self[FREQ_RANGE_KEY].start(),
+ maximum=self[FREQ_RANGE_KEY].stop(),
+ num_steps=1000,
+ )
+ freq_hbox.AddSpacer(3)
- r = self.src.get_freq_range()
- self._fr = Range(r.start(), r.stop(), (r.start()+r.stop())/100, self.src.get_center_freq(), 200)
- self._fw = RangeWidget(self._fr, self.set_freq, 'Center Frequency (Hz)', eng_widget, float)
- self._shrink(self._fw)
- self.top_layout.addWidget(self._fw)
+ except AssertionError:
+ pass
- if hasattr(self, 'ppm') and self.ppm is not None:
- self._fcr = Range(-100, 100, 0.1, self.src.get_freq_corr(), 200)
- self._fcw = RangeWidget(self._fcr, self.set_freq_corr, 'Freq. Correction (ppm)', "counter_slider", float)
- self._shrink(self._fcw)
- self.top_layout.addWidget(self._fcw)
+ if self[FREQ_CORR_KEY] != None: # show frequency correction scrollbar
+
+ corr_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=corr_hbox,
+ label='Freq. Correction (ppm)',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=FREQ_CORR_KEY,
+ )
+ corr_hbox.AddSpacer(5)
+
+ forms.slider(
+ parent=self.panel, sizer=corr_hbox,
+ proportion=3,
+ ps=self,
+ key=FREQ_CORR_KEY,
+ minimum=-100,
+ maximum=+100,
+ num_steps=2010,
+ step_size=0.1,
+ )
+ corr_hbox.AddSpacer(3)
##################################################
# Gain controls
##################################################
- self._add_section("Gains", self.top_layout)
-
- self._gr={}
- self._gw={}
- for gain_name in self.src.get_gain_names():
- rg = self.src.get_gain_range(gain_name)
- self._gr[gain_name] = Range(rg.start(), rg.stop(), rg.step(), self.src.get_gain(gain_name), 100)
- self._gw[gain_name] = RangeWidget(self._gr[gain_name], partial(self.set_named_gain,name=gain_name), '%s Gain (dB):'%gain_name, "counter_slider", float)
- self._shrink(self._gw[gain_name])
- self._gw[gain_name].d_widget.counter.setDecimals(2)
- self.top_layout.addWidget(self._gw[gain_name])
+ gc_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Gain Settings",
+ orient=wx.VERTICAL,
+ bold=True)
+ gc_vbox.AddSpacer(3)
+
+ # Add gain controls to top window sizer
+ vbox.Add(gc_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(5)
+
+ for gain_name in self.get_gain_names():
+ range = self[GAIN_RANGE_KEY(gain_name)]
+ gain = self[GAIN_KEY(gain_name)]
+
+ #print gain_name, gain, range.to_pp_string()
+ if range.start() < range.stop():
+ gain_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ gc_vbox.Add(gain_hbox, 0, wx.EXPAND)
+ gc_vbox.AddSpacer(3)
+
+ gain_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=gain_hbox,
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=GAIN_KEY(gain_name),
+ label=gain_name + " Gain (dB)",
+ )
+ gain_hbox.AddSpacer(5)
+ forms.slider(
+ parent=self.panel, sizer=gain_hbox,
+ proportion=3,
+ ps=self,
+ key=GAIN_KEY(gain_name),
+ minimum=range.start(),
+ maximum=range.stop(),
+ step_size=range.step() or (range.stop() - range.start())/10,
+ )
+ gain_hbox.AddSpacer(3)
##################################################
# Bandwidth controls
##################################################
- if self.bandwidth_ok:
- self._add_section("Bandwidth", self.top_layout)
+ try:
+
+ bw_range = self[BWIDTH_RANGE_KEY]
+ #print bw_range.to_pp_string()
+ if bw_range.start() < bw_range.stop():
+ bwidth_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Bandwidth",
+ orient=wx.VERTICAL,
+ bold=True)
+ bwidth_vbox.AddSpacer(3)
+ bwidth_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ bwidth_vbox.Add(bwidth_hbox, 0, wx.EXPAND)
+ bwidth_vbox.AddSpacer(3)
+
+ vbox.Add(bwidth_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(5)
+
+ bwidth_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=bwidth_hbox,
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=BWIDTH_KEY,
+ label="Bandwidth (Hz)",
+ )
+ bwidth_hbox.AddSpacer(5)
+ forms.slider(
+ parent=self.panel, sizer=bwidth_hbox,
+ proportion=3,
+ ps=self,
+ key=BWIDTH_KEY,
+ minimum=bw_range.start(),
+ maximum=bw_range.stop(),
+ step_size=bw_range.step() or (bw_range.stop() - bw_range.start())/100,
+ )
+ bwidth_hbox.AddSpacer(3)
+
+ except RuntimeError:
+ pass
- r = self.src.get_bandwidth_range()
- self._bwr = Range(r.start(), r.stop(), r.step() or (r.stop() - r.start())/100, self.src.get_bandwidth(), 100)
- self._bww = RangeWidget(self._bwr, self.set_bandwidth, 'Bandwidth (Hz):', eng_widget, float)
- self._shrink(self._bww)
- self.top_layout.addWidget(self._bww)
##################################################
# Sample rate controls
##################################################
- self._add_section("Sample Rate", self.top_layout)
+ sr_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Sample Rate",
+ orient=wx.VERTICAL,
+ bold=True)
+ sr_vbox.AddSpacer(3)
+ # First row of sample rate controls
+ sr_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ sr_vbox.Add(sr_hbox, 0, wx.EXPAND)
+ sr_vbox.AddSpacer(5)
+
+ # Add sample rate controls to top window sizer
+ vbox.Add(sr_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(5)
+
+ sr_hbox.AddSpacer(3)
+ self.sample_rate_text = forms.text_box(
+ parent=self.panel, sizer=sr_hbox,
+ label='Sample Rate (Hz)',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=SAMP_RATE_KEY,
+ )
+ sr_hbox.AddSpacer(5)
+
+ #forms.slider(
+ # parent=self.panel, sizer=sr_hbox,
+ # proportion=3,
+ # ps=self,
+ # key=SAMP_RATE_KEY,
+ # minimum=self[SAMP_RANGE_KEY].start(),
+ # maximum=self[SAMP_RANGE_KEY].stop(),
+ # step_size=self[SAMP_RANGE_KEY].step(),
+ #)
+ #sr_hbox.AddSpacer(3)
- r = self.src.get_sample_rates()
- self._srr = Range(r.start(), r.stop(), r.step() or (r.stop() - r.start())/100, self.src.get_sample_rate(), 100)
- self._srw = RangeWidget(self._srr, self.set_sample_rate, 'Sample Rate (Hz)', eng_widget, float)
- self._shrink(self._srw)
- self.top_layout.addWidget(self._srw)
##################################################
# File recording controls
##################################################
- self._add_section("File recording", self.top_layout)
-
- wid = Qt.QWidget()
-
- layout = Qt.QHBoxLayout()
- layout.setContentsMargins(0, 0, 0, 0)
-
- self._frl = Qt.QLabel('File Name')
- layout.addWidget(self._frl)
-
- self._fre = Qt.QLineEdit()
- layout.addWidget(self._fre)
-
- self._frb = Qt.QPushButton('REC')
- layout.addWidget(self._frb)
-
- wid.setLayout(layout)
- self.top_layout.addWidget(wid)
-
- self.recording = 0
- def record_callback():
- self.recording = 1-self.recording
- if self.recording:
- self._srw.setDisabled(True)
- self._fre.setDisabled(True)
- self._frb.setText('STOP')
+ rec_vbox = forms.static_box_sizer(parent=self.panel,
+ label="File recording",
+ orient=wx.VERTICAL,
+ bold=True)
+ rec_vbox.AddSpacer(3)
+ # First row of sample rate controls
+ rec_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ rec_vbox.Add(rec_hbox, 0, wx.EXPAND)
+ rec_vbox.AddSpacer(5)
+
+ # Add sample rate controls to top window sizer
+ vbox.Add(rec_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(5)
+
+ rec_hbox.AddSpacer(3)
+ self.record_text = forms.text_box(
+ parent=self.panel, sizer=rec_hbox,
+ label='File Name',
+ proportion=1,
+ ps=self,
+ key='record',
+ converter=forms.str_converter(),
+ )
+ rec_hbox.AddSpacer(5)
+
+ def record_callback(value):
+ if value:
+ self.sample_rate_text.Disable()
+ self.record_text.Disable()
self.rec_file_name = self.record_to_filename()
- print("Recording samples to ", self.rec_file_name)
+ print "Recording samples to ", self.rec_file_name
self.file_sink.open(self.rec_file_name);
else:
- self._srw.setDisabled(False)
- self._fre.setDisabled(False)
- self._frb.setText('REC')
+ self.sample_rate_text.Enable()
+ self.record_text.Enable()
self.file_sink.close()
- print("Finished recording to", self.rec_file_name)
+ print "Finished recording to", self.rec_file_name
- self._fre.returnPressed.connect(record_callback)
- self._frb.clicked.connect(record_callback)
+ forms.toggle_button(
+ sizer=rec_hbox,
+ parent=self.panel,
+ false_label='REC',
+ true_label='STOP',
+ value=False,
+ callback=record_callback,
+ )
##################################################
# DC Offset controls
##################################################
if self.dc_offset_mode != None:
- self._add_section("DC Offset Correction", self.top_layout)
-
- wid = Qt.QWidget()
- layout = Qt.QHBoxLayout()
- layout.setContentsMargins(0, 0, 0, 0)
-
- self._dcb = self._chooser(["Off", "Manual", "Auto"], self.set_dc_offset_mode, self.dc_offset_mode)
- layout.addWidget(self._dcb)
-
- self._dcrr = Range(-1, +1, 0.001, 0, 20)
- self._dcrw = RangeWidget(self._dcrr, self.set_dc_offset_real, 'Real', "counter_slider", float)
- self._shrink(self._dcrw)
- layout.addWidget(self._dcrw)
-
- self._dcir = Range(-1, +1, 0.001, 0, 20)
- self._dciw = RangeWidget(self._dcrr, self.set_dc_offset_imag, 'Imag', "counter_slider", float)
- self._shrink(self._dciw)
- layout.addWidget(self._dciw)
-
- wid.setLayout(layout)
- self.top_layout.addWidget(wid)
+ dc_offset_vbox = forms.static_box_sizer(parent=self.panel,
+ label="DC Offset Correction",
+ orient=wx.VERTICAL,
+ bold=True)
+ dc_offset_vbox.AddSpacer(3)
+ # First row of sample rate controls
+ dc_offset_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ dc_offset_vbox.Add(dc_offset_hbox, 0, wx.EXPAND)
+ dc_offset_vbox.AddSpacer(3)
+
+ # Add frequency controls to top window sizer
+ vbox.Add(dc_offset_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(3)
+
+ self.dc_offset_mode_chooser = forms.radio_buttons(
+ parent=self.panel,
+ value=self.dc_offset_mode,
+ callback=self.set_dc_offset_mode,
+ label='',
+ choices=[0, 1, 2],
+ labels=["Off", "Manual", "Auto"],
+ style=wx.RA_HORIZONTAL,
+ )
+ dc_offset_hbox.Add(self.dc_offset_mode_chooser)
+ dc_offset_hbox.AddSpacer(3)
+
+ dc_offset_hbox.AddSpacer(3)
+ self.dc_offset_real_text = forms.text_box(
+ parent=self.panel, sizer=dc_offset_hbox,
+ label='Real',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key='dc_offset_real',
+ )
+ dc_offset_hbox.AddSpacer(3)
+
+ self.dc_offset_real_slider = forms.slider(
+ parent=self.panel, sizer=dc_offset_hbox,
+ proportion=3,
+ minimum=-1,
+ maximum=+1,
+ step_size=0.001,
+ ps=self,
+ key='dc_offset_real',
+ )
+ dc_offset_hbox.AddSpacer(3)
+
+ dc_offset_hbox.AddSpacer(3)
+ self.dc_offset_imag_text = forms.text_box(
+ parent=self.panel, sizer=dc_offset_hbox,
+ label='Imag',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key='dc_offset_imag',
+ )
+ dc_offset_hbox.AddSpacer(3)
+
+ self.dc_offset_imag_slider = forms.slider(
+ parent=self.panel, sizer=dc_offset_hbox,
+ proportion=3,
+ minimum=-1,
+ maximum=+1,
+ step_size=0.001,
+ ps=self,
+ key='dc_offset_imag',
+ )
+ dc_offset_hbox.AddSpacer(3)
##################################################
# IQ Imbalance controls
##################################################
if self.iq_balance_mode != None:
- self._add_section("IQ Imbalance Correction", self.top_layout)
-
- wid = Qt.QWidget()
-
- layout = Qt.QHBoxLayout()
- layout.setContentsMargins(0, 0, 0, 0)
-
- self._iqb = self._chooser(["Off", "Manual", "Auto"], self.set_dc_offset_mode, self.iq_balance_mode)
- layout.addWidget(self._iqb)
-
- self._iqmr = Range(-1, +1, 0.001, 0, 20)
- self._iqmw = RangeWidget(self._iqmr, self.set_iq_balance_mag, 'Mag', "counter_slider", float)
- self._shrink(self._iqmw)
- layout.addWidget(self._iqmw)
-
- self._iqpr = Range(-1, +1, 0.001, 0, 20)
- self._iqpw = RangeWidget(self._iqpr, self.set_iq_balance_pha, 'Pha', "counter_slider", float)
- self._shrink(self._iqpw)
- layout.addWidget(self._iqpw)
- wid.setLayout(layout)
- self.top_layout.addWidget(wid)
+ iq_balance_vbox = forms.static_box_sizer(parent=self.panel,
+ label="IQ Imbalance Correction",
+ orient=wx.VERTICAL,
+ bold=True)
+ iq_balance_vbox.AddSpacer(3)
+ # First row of sample rate controls
+ iq_balance_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ iq_balance_vbox.Add(iq_balance_hbox, 0, wx.EXPAND)
+ iq_balance_vbox.AddSpacer(3)
+
+ # Add frequency controls to top window sizer
+ vbox.Add(iq_balance_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(3)
+
+ self.iq_balance_mode_chooser = forms.radio_buttons(
+ parent=self.panel,
+ value=self.iq_balance_mode,
+ callback=self.set_iq_balance_mode,
+ label='',
+ choices=[0, 1, 2],
+ labels=["Off", "Manual", "Auto"],
+ style=wx.RA_HORIZONTAL,
+ )
+ iq_balance_hbox.Add(self.iq_balance_mode_chooser)
+ iq_balance_hbox.AddSpacer(3)
+
+ iq_balance_hbox.AddSpacer(3)
+ self.iq_balance_mag_text = forms.text_box(
+ parent=self.panel, sizer=iq_balance_hbox,
+ label='Mag',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key='iq_balance_mag',
+ )
+ iq_balance_hbox.AddSpacer(3)
+
+ self.iq_balance_mag_slider = forms.slider(
+ parent=self.panel, sizer=iq_balance_hbox,
+ proportion=3,
+ minimum=-1,
+ maximum=+1,
+ step_size=0.001,
+ ps=self,
+ key='iq_balance_mag',
+ )
+ iq_balance_hbox.AddSpacer(3)
+
+ iq_balance_hbox.AddSpacer(3)
+ self.iq_balance_pha_text = forms.text_box(
+ parent=self.panel, sizer=iq_balance_hbox,
+ label='Phase',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key='iq_balance_pha',
+ )
+ iq_balance_hbox.AddSpacer(3)
+
+ self.iq_balance_pha_slider = forms.slider(
+ parent=self.panel, sizer=iq_balance_hbox,
+ proportion=3,
+ minimum=-1,
+ maximum=+1,
+ step_size=0.001,
+ ps=self,
+ key='iq_balance_pha',
+ )
+ iq_balance_hbox.AddSpacer(3)
def set_dc_offset_mode(self, dc_offset_mode):
if dc_offset_mode == 1:
- self._dcrw.setDisabled(False)
- self._dciw.setDisabled(False)
+ self.dc_offset_real_text.Enable()
+ self.dc_offset_real_slider.Enable()
+ self.dc_offset_imag_text.Enable()
+ self.dc_offset_imag_slider.Enable()
- self.set_dc_offset()
+ self.set_dc_offset(0)
else:
- self._dcrw.setDisabled(True)
- self._dciw.setDisabled(True)
+ self.dc_offset_real_text.Disable()
+ self.dc_offset_real_slider.Disable()
+ self.dc_offset_imag_text.Disable()
+ self.dc_offset_imag_slider.Disable()
self.dc_offset_mode = dc_offset_mode
self.src.set_dc_offset_mode(dc_offset_mode)
+ self.dc_offset_mode_chooser.set_value(self.dc_offset_mode)
- def set_dc_offset_real(self, value):
- self.dc_offset_real = value
- self.set_dc_offset()
-
- def set_dc_offset_imag(self, value):
- self.dc_offset_imag = value
- self.set_dc_offset()
-
- def set_dc_offset(self):
- correction = complex(self.dc_offset_real, self.dc_offset_imag)
+ def set_dc_offset(self, value):
+ correction = complex( self['dc_offset_real'], self['dc_offset_imag'] )
try:
- self.src.set_dc_offset(correction)
+ self.src.set_dc_offset( correction )
if self._verbose:
- print("Set DC offset to", correction)
+ print "Set DC offset to", correction
except RuntimeError as ex:
- print(ex)
+ print ex
def set_iq_balance_mode(self, iq_balance_mode):
if iq_balance_mode == 1:
- self._iqpw.setDisabled(False)
- self._iqmw.setDisabled(False)
+ self.iq_balance_mag_text.Enable()
+ self.iq_balance_mag_slider.Enable()
+ self.iq_balance_pha_text.Enable()
+ self.iq_balance_pha_slider.Enable()
- self.set_iq_balance()
+ self.set_iq_balance(0)
else:
- self._iqpw.setDisabled(True)
- self._iqmw.setDisabled(True)
+ self.iq_balance_mag_text.Disable()
+ self.iq_balance_mag_slider.Disable()
+ self.iq_balance_pha_text.Disable()
+ self.iq_balance_pha_slider.Disable()
self.iq_balance_mode = iq_balance_mode
self.src.set_iq_balance_mode(iq_balance_mode)
+ self.iq_balance_mode_chooser.set_value(self.iq_balance_mode)
- def set_iq_balance_mag(self, value):
- self.iq_balance_mag = value
- self.set_iq_balance()
-
- def set_iq_balance_pha(self, value):
- self.iq_balance_pha = value
- self.set_iq_balance()
-
- def set_iq_balance(self):
- correction = complex(self.iq_balance_mag, self.iq_balance_pha)
+ def set_iq_balance(self, value):
+ correction = complex( self['iq_balance_mag'], self['iq_balance_pha'] )
try:
- self.src.set_iq_balance(correction)
+ self.src.set_iq_balance( correction )
if self._verbose:
- print("Set IQ balance to", correction)
+ print "Set IQ balance to", correction
except RuntimeError as ex:
- print(ex)
+ print ex
def set_sample_rate(self, samp_rate):
samp_rate = self.src.set_sample_rate(samp_rate)
- if hasattr(self.scope, 'set_frequency_range'):
- self.scope.set_frequency_range(self.src.get_center_freq(), samp_rate)
if hasattr(self.scope, 'set_sample_rate'):
self.scope.set_sample_rate(samp_rate)
if self._verbose:
- print("Set sample rate to:", samp_rate)
+ print "Set sample rate to:", samp_rate
try:
- if hasattr(self._bww.d_widget, 'setValue'):
- self._bww.d_widget.setValue(samp_rate)
- else:
- self._bww.d_widget.counter.setValue(samp_rate)
- except (RuntimeError, AttributeError):
+ self[BWIDTH_KEY] = self.set_bandwidth(samp_rate)
+ except RuntimeError:
pass
return samp_rate
+ def get_gain_names(self):
+ return self.src.get_gain_names()
+
def set_named_gain(self, gain, name):
- if self._verbose:
- print("Trying to set " + name + " gain to:", gain)
+ if gain is None:
+ g = self[GAIN_RANGE_KEY(name)]
+ gain = float(g.start()+g.stop())/2
+ if self._verbose:
+ print "Using auto-calculated mid-point gain"
+ self[GAIN_KEY(name)] = gain
+ return
gain = self.src.set_gain(gain, name)
if self._verbose:
- print("Set " + name + " gain to:", gain)
+ print "Set " + name + " gain to:", gain
def set_bandwidth(self, bw):
- if self._verbose:
- print("Trying to set bandwidth to:", bw)
- clipped_bw = self.src.get_bandwidth_range().clip(bw)
- if self._verbose:
- print("Clipping bandwidth to:", clipped_bw)
+ clipped_bw = self[BWIDTH_RANGE_KEY].clip(bw)
if self.src.get_bandwidth() != clipped_bw:
bw = self.src.set_bandwidth(clipped_bw)
if self._verbose:
- print("Set bandwidth to:", bw)
+ print "Set bandwidth to:", bw
return bw
+ def set_freq_from_callback(self, freq):
+ freq = self.src.set_center_freq(freq)
+ self[CENTER_FREQ_KEY] = freq;
+
def set_freq(self, freq):
+ if freq is None:
+ f = self[FREQ_RANGE_KEY]
+ freq = float(f.start()+f.stop())/2.0
+ if self._verbose:
+ print "Using auto-calculated mid-point frequency"
+ self[CENTER_FREQ_KEY] = freq
+ return
freq = self.src.set_center_freq(freq)
- if hasattr(self.scope, 'set_frequency_range'):
- self.scope.set_frequency_range(freq, self.src.get_sample_rate())
if hasattr(self.scope, 'set_baseband_freq'):
self.scope.set_baseband_freq(freq)
- try:
- if hasattr(self._fw.d_widget, 'setValue'):
- self._fw.d_widget.setValue(freq)
- else:
- self._fw.d_widget.counter.setValue(freq)
- except (RuntimeError, AttributeError):
- pass
-
if freq is not None:
if self._verbose:
- print("Set center frequency to %.10g"%freq)
+ print "Set center frequency to", freq
elif self._verbose:
- print("Failed to set freq.")
+ print "Failed to set freq."
return freq
def set_freq_corr(self, ppm):
- self.ppm = self.src.set_freq_corr(ppm)
- if self._verbose:
- print("Set frequency correction to:", self.ppm)
-
-
-def main():
- qapp = Qt.QApplication(sys.argv)
-
- tb = app_top_block(qapp.arguments(), "osmocom Spectrum Browser")
- tb.start()
- tb.show()
-
- def sig_handler(sig=None, frame=None):
- print("caught signal")
- Qt.QApplication.quit()
-
- signal.signal(signal.SIGINT, sig_handler)
- signal.signal(signal.SIGTERM, sig_handler)
-
- # this timer is necessary for signals (^C) to work
- timer = Qt.QTimer()
- timer.start(500)
- timer.timeout.connect(lambda: None)
+ if ppm is None:
+ ppm = 0.0
+ if self._verbose:
+ print "Using frequency corrrection of", ppm
+ self[FREQ_CORR_KEY] = ppm
+ return
- def quitting():
- tb.stop()
- tb.wait()
- qapp.aboutToQuit.connect(quitting)
- qapp.exec_()
+ ppm = self.src.set_freq_corr(ppm)
+ if self._verbose:
+ print "Set frequency correction to:", ppm
+def main ():
+ app = stdgui2.stdapp(app_top_block, "osmocom Spectrum Browser", nstatus=1)
+ app.MainLoop()
if __name__ == '__main__':
- main()
+ main ()
diff --git a/apps/osmocom_siggen b/apps/osmocom_siggen
index 1727f44..bd92eac 100755
--- a/apps/osmocom_siggen
+++ b/apps/osmocom_siggen
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
#
# Copyright 2009,2011,2012 Free Software Foundation, Inc.
#
diff --git a/apps/osmocom_siggen_nogui b/apps/osmocom_siggen_nogui
index 5370cd0..0283fcf 100755
--- a/apps/osmocom_siggen_nogui
+++ b/apps/osmocom_siggen_nogui
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
#
# Copyright 2008,2009,2011,2012 Free Software Foundation, Inc.
#
@@ -26,19 +26,19 @@ import sys
def main():
if gr.enable_realtime_scheduling() != gr.RT_OK:
- print("Note: failed to enable realtime scheduling, continuing")
+ print "Note: failed to enable realtime scheduling, continuing"
# Grab command line options and create top block
try:
(options, args) = osmocom_siggen.get_options()
tb = osmocom_siggen.top_block(options, args)
- except RuntimeError as e:
- print(e)
+ except RuntimeError, e:
+ print e
sys.exit(1)
tb.start()
- input('Press Enter to quit: ')
+ raw_input('Press Enter to quit: ')
tb.stop()
tb.wait()
diff --git a/apps/osmocom_spectrum_sense b/apps/osmocom_spectrum_sense
index 9fea6f0..ea365bb 100755
--- a/apps/osmocom_spectrum_sense
+++ b/apps/osmocom_spectrum_sense
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
#
# Copyright 2005,2007,2011 Free Software Foundation, Inc.
#
@@ -71,13 +71,13 @@ class tune(gr.feval_dd):
# wait until msgq is empty before continuing
while(self.tb.msgq.full_p()):
- #print("msgq full, holding..")
+ #print "msgq full, holding.."
time.sleep(0.1)
return new_freq
- except Exception as e:
- print("tune: Exception: ", e)
+ except Exception, e:
+ print "tune: Exception: ", e
class parse_msg(object):
@@ -147,7 +147,7 @@ class my_top_block(gr.top_block):
realtime = True
else:
realtime = False
- print("Note: failed to enable realtime scheduling")
+ print "Note: failed to enable realtime scheduling"
# build graph
self.u = osmosdr.source(options.args)
@@ -155,7 +155,7 @@ class my_top_block(gr.top_block):
try:
self.u.get_sample_rates().start()
except RuntimeError:
- print("Source has no sample rates (wrong device arguments?).")
+ print "Source has no sample rates (wrong device arguments?)."
sys.exit(1)
# Set the antenna
@@ -218,7 +218,7 @@ class my_top_block(gr.top_block):
options.gain = float(g.start()+g.stop())/2.0
self.set_gain(options.gain)
- print("gain =", options.gain)
+ print "gain =", options.gain
def set_next_freq(self):
target_freq = self.next_freq
@@ -227,7 +227,7 @@ class my_top_block(gr.top_block):
self.next_freq = self.min_center_freq
if not self.set_freq(target_freq):
- print("Failed to set frequency to", target_freq)
+ print "Failed to set frequency to", target_freq
sys.exit(1)
return target_freq
@@ -259,9 +259,9 @@ def main_loop(tb):
def bin_freq(i_bin, center_freq):
#hz_per_bin = tb.usrp_rate / tb.fft_size
freq = center_freq - (tb.usrp_rate / 2) + (tb.channel_bandwidth * i_bin)
- #print("freq original:",freq)
+ #print "freq original:",freq
#freq = nearest_freq(freq, tb.channel_bandwidth)
- #print("freq rounded:",freq)
+ #print "freq rounded:",freq
return freq
bin_start = int(tb.fft_size * ((1 - 0.75) / 2))
@@ -287,7 +287,7 @@ def main_loop(tb):
power_db = 10*math.log10(m.data[i_bin]/tb.usrp_rate) - noise_floor_db
if (power_db > tb.squelch_threshold) and (freq >= tb.min_freq) and (freq <= tb.max_freq):
- print(datetime.now(), "center_freq", center_freq, "freq", freq, "power_db", power_db, "noise_floor_db", noise_floor_db)
+ print datetime.now(), "center_freq", center_freq, "freq", freq, "power_db", power_db, "noise_floor_db", noise_floor_db
if __name__ == '__main__':
t = ThreadClass()
diff --git a/cmake/Modules/CMakeParseArgumentsCopy.cmake b/cmake/Modules/CMakeParseArgumentsCopy.cmake
new file mode 100644
index 0000000..66016cb
--- /dev/null
+++ b/cmake/Modules/CMakeParseArgumentsCopy.cmake
@@ -0,0 +1,138 @@
+# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)
+#
+# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions for
+# parsing the arguments given to that macro or function.
+# It processes the arguments and defines a set of variables which hold the
+# values of the respective options.
+#
+# The <options> argument contains all options for the respective macro,
+# i.e. keywords which can be used when calling the macro without any value
+# following, like e.g. the OPTIONAL keyword of the install() command.
+#
+# The <one_value_keywords> argument contains all keywords for this macro
+# which are followed by one value, like e.g. DESTINATION keyword of the
+# install() command.
+#
+# The <multi_value_keywords> argument contains all keywords for this macro
+# which can be followed by more than one value, like e.g. the TARGETS or
+# FILES keywords of the install() command.
+#
+# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
+# keywords listed in <options>, <one_value_keywords> and
+# <multi_value_keywords> a variable composed of the given <prefix>
+# followed by "_" and the name of the respective keyword.
+# These variables will then hold the respective value from the argument list.
+# For the <options> keywords this will be TRUE or FALSE.
+#
+# All remaining arguments are collected in a variable
+# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see whether
+# your macro was called with unrecognized parameters.
+#
+# As an example here a my_install() macro, which takes similar arguments as the
+# real install() command:
+#
+# function(MY_INSTALL)
+# set(options OPTIONAL FAST)
+# set(oneValueArgs DESTINATION RENAME)
+# set(multiValueArgs TARGETS CONFIGURATIONS)
+# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
+# ...
+#
+# Assume my_install() has been called like this:
+# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
+#
+# After the cmake_parse_arguments() call the macro will have set the following
+# variables:
+# MY_INSTALL_OPTIONAL = TRUE
+# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
+# MY_INSTALL_DESTINATION = "bin"
+# MY_INSTALL_RENAME = "" (was not used)
+# MY_INSTALL_TARGETS = "foo;bar"
+# MY_INSTALL_CONFIGURATIONS = "" (was not used)
+# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
+#
+# You can the continue and process these variables.
+#
+# Keywords terminate lists of values, e.g. if directly after a one_value_keyword
+# another recognized keyword follows, this is interpreted as the beginning of
+# the new option.
+# E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in
+# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would
+# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefore.
+
+#=============================================================================
+# Copyright 2010 Alexander Neundorf <neundorf@kde.org>
+#
+# 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.)
+
+
+if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
+ return()
+endif()
+set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
+
+
+function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
+ # first set all result variables to empty/FALSE
+ foreach(arg_name ${_singleArgNames} ${_multiArgNames})
+ set(${prefix}_${arg_name})
+ endforeach(arg_name)
+
+ foreach(option ${_optionNames})
+ set(${prefix}_${option} FALSE)
+ endforeach(option)
+
+ set(${prefix}_UNPARSED_ARGUMENTS)
+
+ set(insideValues FALSE)
+ set(currentArgName)
+
+ # now iterate over all arguments and fill the result variables
+ foreach(currentArg ${ARGN})
+ list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword
+ list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword
+ list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword
+
+ if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1)
+ if(insideValues)
+ if("${insideValues}" STREQUAL "SINGLE")
+ set(${prefix}_${currentArgName} ${currentArg})
+ set(insideValues FALSE)
+ elseif("${insideValues}" STREQUAL "MULTI")
+ list(APPEND ${prefix}_${currentArgName} ${currentArg})
+ endif()
+ else(insideValues)
+ list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
+ endif(insideValues)
+ else()
+ if(NOT ${optionIndex} EQUAL -1)
+ set(${prefix}_${currentArg} TRUE)
+ set(insideValues FALSE)
+ elseif(NOT ${singleArgIndex} EQUAL -1)
+ set(currentArgName ${currentArg})
+ set(${prefix}_${currentArgName})
+ set(insideValues "SINGLE")
+ elseif(NOT ${multiArgIndex} EQUAL -1)
+ set(currentArgName ${currentArg})
+ set(${prefix}_${currentArgName})
+ set(insideValues "MULTI")
+ endif()
+ endif()
+
+ endforeach(currentArg)
+
+ # propagate the result variables to the caller:
+ foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
+ set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
+ endforeach(arg_name)
+ set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
+
+endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs)
diff --git a/cmake/Modules/FindGnuradioFCD.cmake b/cmake/Modules/FindGnuradioFCD.cmake
new file mode 100644
index 0000000..e7d7670
--- /dev/null
+++ b/cmake/Modules/FindGnuradioFCD.cmake
@@ -0,0 +1,34 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_GNURADIO_FCD gnuradio-fcd)
+
+FIND_PATH(
+ GNURADIO_FCD_INCLUDE_DIRS
+ NAMES gnuradio/fcd/api.h
+ HINTS $ENV{GNURADIO_FCD_DIR}/include
+ ${PC_GNURADIO_FCD_INCLUDEDIR}
+ PATHS /usr/local/include
+ /usr/include
+)
+
+FIND_LIBRARY(
+ GNURADIO_FCD_LIBRARIES
+ NAMES gnuradio-fcd
+ HINTS $ENV{GNURADIO_FCD_DIR}/lib
+ ${PC_GNURADIO_FCD_LIBDIR}
+ PATHS /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+)
+
+if(GNURADIO_FCD_INCLUDE_DIRS AND GNURADIO_FCD_LIBRARIES)
+ set(GNURADIO_FCD_FOUND TRUE CACHE INTERNAL "gnuradio-fcd found")
+ message(STATUS "Found gnuradio-fcd: ${GNURADIO_FCD_INCLUDE_DIRS}, ${GNURADIO_FCD_LIBRARIES}")
+else(GNURADIO_FCD_INCLUDE_DIRS AND GNURADIO_FCD_LIBRARIES)
+ set(GNURADIO_FCD_FOUND FALSE CACHE INTERNAL "gnuradio-fcd found")
+ message(STATUS "gnuradio-fcd not found.")
+endif(GNURADIO_FCD_INCLUDE_DIRS AND GNURADIO_FCD_LIBRARIES)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_FCD DEFAULT_MSG GNURADIO_FCD_LIBRARIES GNURADIO_FCD_INCLUDE_DIRS)
+MARK_AS_ADVANCED(GNURADIO_FCD_LIBRARIES GNURADIO_FCD_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindGnuradioFCDPP.cmake b/cmake/Modules/FindGnuradioFCDPP.cmake
index f81fe8a..c6f03f1 100644
--- a/cmake/Modules/FindGnuradioFCDPP.cmake
+++ b/cmake/Modules/FindGnuradioFCDPP.cmake
@@ -1,18 +1,25 @@
-if(NOT GNURADIO_FCDPP_FOUND)
- pkg_check_modules (GNURADIO_FCDPP_PKG libgnuradio-fcdproplus)
- find_path(GNURADIO_FCDPP_INCLUDE_DIRS NAMES fcdproplus/api.h
- PATHS
- ${GNURADIO_FCDPP_PKG_INCLUDE_DIRS}
- /usr/include
- /usr/local/include
- )
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_GNURADIO_FCDPP gnuradio-fcdproplus)
- find_library(GNURADIO_FCDPP_LIBRARIES NAMES gnuradio-fcdproplus
- PATHS
- ${GNURADIO_FCDPP_PKG_LIBRARY_DIRS}
- /usr/lib
- /usr/local/lib
- )
+FIND_PATH(
+ GNURADIO_FCDPP_INCLUDE_DIRS
+ NAMES fcdproplus/api.h
+ HINTS $ENV{GNURADIO_FCDPP_DIR}/include
+ ${PC_GNURADIO_FCDPP_INCLUDEDIR}
+ PATHS /usr/local/include
+ /usr/include
+)
+
+FIND_LIBRARY(
+ GNURADIO_FCDPP_LIBRARIES
+ NAMES gnuradio-fcdproplus
+ HINTS $ENV{GNURADIO_FCDPP_DIR}/lib
+ ${PC_GNURADIO_FCDPP_LIBDIR}
+ PATHS /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+)
if(GNURADIO_FCDPP_INCLUDE_DIRS AND GNURADIO_FCDPP_LIBRARIES)
set(GNURADIO_FCDPP_FOUND TRUE CACHE INTERNAL "gnuradio-fcdproplus found")
@@ -22,6 +29,6 @@ else(GNURADIO_FCDPP_INCLUDE_DIRS AND GNURADIO_FCDPP_LIBRARIES)
message(STATUS "gnuradio-fcdproplus not found.")
endif(GNURADIO_FCDPP_INCLUDE_DIRS AND GNURADIO_FCDPP_LIBRARIES)
-mark_as_advanced(GNURADIO_FCDPP_LIBRARIES GNURADIO_FCDPP_INCLUDE_DIRS)
-
-endif(NOT GNURADIO_FCDPP_FOUND)
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_FCDPP DEFAULT_MSG GNURADIO_FCDPP_LIBRARIES GNURADIO_FCDPP_INCLUDE_DIRS)
+MARK_AS_ADVANCED(GNURADIO_FCDPP_LIBRARIES GNURADIO_FCDPP_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindGnuradioIQBalance.cmake b/cmake/Modules/FindGnuradioIQBalance.cmake
new file mode 100644
index 0000000..c381d1c
--- /dev/null
+++ b/cmake/Modules/FindGnuradioIQBalance.cmake
@@ -0,0 +1,29 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_GNURADIO_IQBALANCE gnuradio-iqbalance)
+
+FIND_PATH(
+ GNURADIO_IQBALANCE_INCLUDE_DIRS
+ NAMES gnuradio/iqbalance/api.h
+ HINTS $ENV{GNURADIO_IQBALANCE_DIR}/include
+ ${PC_GNURADIO_IQBALANCE_INCLUDEDIR}
+ ${CMAKE_INSTALL_PREFIX}/include
+ PATHS /usr/local/include
+ /usr/include
+)
+
+FIND_LIBRARY(
+ GNURADIO_IQBALANCE_LIBRARIES
+ NAMES gnuradio-iqbalance
+ HINTS $ENV{GNURADIO_IQBALANCE_DIR}/lib
+ ${PC_GNURADIO_IQBALANCE_LIBDIR}
+ ${CMAKE_INSTALL_PREFIX}/lib64
+ ${CMAKE_INSTALL_PREFIX}/lib
+ PATHS /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_IQBALANCE DEFAULT_MSG GNURADIO_IQBALANCE_LIBRARIES GNURADIO_IQBALANCE_INCLUDE_DIRS)
+MARK_AS_ADVANCED(GNURADIO_IQBALANCE_LIBRARIES GNURADIO_IQBALANCE_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindGnuradioUHD.cmake b/cmake/Modules/FindGnuradioUHD.cmake
new file mode 100644
index 0000000..f99daf0
--- /dev/null
+++ b/cmake/Modules/FindGnuradioUHD.cmake
@@ -0,0 +1,34 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_GNURADIO_UHD gnuradio-uhd)
+
+FIND_PATH(
+ GNURADIO_UHD_INCLUDE_DIRS
+ NAMES gnuradio/uhd/api.h
+ HINTS $ENV{GNURADIO_UHD_DIR}/include
+ ${PC_GNURADIO_UHD_INCLUDEDIR}
+ PATHS /usr/local/include
+ /usr/include
+)
+
+FIND_LIBRARY(
+ GNURADIO_UHD_LIBRARIES
+ NAMES gnuradio-uhd
+ HINTS $ENV{GNURADIO_UHD_DIR}/lib
+ ${PC_GNURADIO_UHD_LIBDIR}
+ PATHS /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+)
+
+if(GNURADIO_UHD_INCLUDE_DIRS AND GNURADIO_UHD_LIBRARIES)
+ set(GNURADIO_UHD_FOUND TRUE CACHE INTERNAL "gnuradio-uhd found")
+ message(STATUS "Found gnuradio-uhd: ${GNURADIO_UHD_INCLUDE_DIRS}, ${GNURADIO_UHD_LIBRARIES}")
+else(GNURADIO_UHD_INCLUDE_DIRS AND GNURADIO_UHD_LIBRARIES)
+ set(GNURADIO_UHD_FOUND FALSE CACHE INTERNAL "gnuradio-uhd found")
+ message(STATUS "gnuradio-uhd not found.")
+endif(GNURADIO_UHD_INCLUDE_DIRS AND GNURADIO_UHD_LIBRARIES)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_UHD DEFAULT_MSG GNURADIO_UHD_LIBRARIES GNURADIO_UHD_INCLUDE_DIRS)
+MARK_AS_ADVANCED(GNURADIO_UHD_LIBRARIES GNURADIO_UHD_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindLibAIRSPYHF.cmake b/cmake/Modules/FindLibAIRSPYHF.cmake
deleted file mode 100644
index edb0dda..0000000
--- a/cmake/Modules/FindLibAIRSPYHF.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-INCLUDE(FindPkgConfig)
-PKG_CHECK_MODULES(PC_LIBAIRSPYHF libairspyhf)
-
-FIND_PATH(
- LIBAIRSPYHF_INCLUDE_DIRS
- NAMES libairspyhf/airspyhf.h
- HINTS $ENV{LIBAIRSPYHF_DIR}/include
- ${PC_LIBAIRSPYHF_INCLUDEDIR}
- PATHS /usr/local/include
- /usr/include
-)
-
-FIND_LIBRARY(
- LIBAIRSPYHF_LIBRARIES
- NAMES airspyhf
- HINTS $ENV{LIBAIRSPYHF_DIR}/lib
- ${PC_LIBAIRSPYHF_LIBDIR}
- PATHS /usr/local/lib
- /usr/lib
-)
-
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBAIRSPYHF DEFAULT_MSG LIBAIRSPYHF_LIBRARIES LIBAIRSPYHF_INCLUDE_DIRS)
-MARK_AS_ADVANCED(LIBAIRSPYHF_LIBRARIES LIBAIRSPYHF_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindLibMiriSDR.cmake b/cmake/Modules/FindLibMiriSDR.cmake
new file mode 100644
index 0000000..cdb673f
--- /dev/null
+++ b/cmake/Modules/FindLibMiriSDR.cmake
@@ -0,0 +1,27 @@
+if(NOT LIBMIRISDR_FOUND)
+ pkg_check_modules (LIBMIRISDR_PKG libmirisdr)
+ find_path(LIBMIRISDR_INCLUDE_DIRS NAMES mirisdr.h
+ PATHS
+ ${LIBMIRISDR_PKG_INCLUDE_DIRS}
+ /usr/include
+ /usr/local/include
+ )
+
+ find_library(LIBMIRISDR_LIBRARIES NAMES mirisdr
+ PATHS
+ ${LIBMIRISDR_PKG_LIBRARY_DIRS}
+ /usr/lib
+ /usr/local/lib
+ )
+
+if(LIBMIRISDR_INCLUDE_DIRS AND LIBMIRISDR_LIBRARIES)
+ set(LIBMIRISDR_FOUND TRUE CACHE INTERNAL "libmirisdr found")
+ message(STATUS "Found libmirisdr: ${LIBMIRISDR_INCLUDE_DIRS}, ${LIBMIRISDR_LIBRARIES}")
+else(LIBMIRISDR_INCLUDE_DIRS AND LIBMIRISDR_LIBRARIES)
+ set(LIBMIRISDR_FOUND FALSE CACHE INTERNAL "libmirisdr found")
+ message(STATUS "libmirisdr not found.")
+endif(LIBMIRISDR_INCLUDE_DIRS AND LIBMIRISDR_LIBRARIES)
+
+mark_as_advanced(LIBMIRISDR_LIBRARIES LIBMIRISDR_INCLUDE_DIRS)
+
+endif(NOT LIBMIRISDR_FOUND)
diff --git a/cmake/Modules/FindLibOsmoSDR.cmake b/cmake/Modules/FindLibOsmoSDR.cmake
new file mode 100644
index 0000000..a772e68
--- /dev/null
+++ b/cmake/Modules/FindLibOsmoSDR.cmake
@@ -0,0 +1,27 @@
+if(NOT LIBOSMOSDR_FOUND)
+ pkg_check_modules (LIBOSMOSDR_PKG libosmosdr)
+ find_path(LIBOSMOSDR_INCLUDE_DIRS NAMES osmosdr.h
+ PATHS
+ ${LIBOSMOSDR_PKG_INCLUDE_DIRS}
+ /usr/include
+ /usr/local/include
+ )
+
+ find_library(LIBOSMOSDR_LIBRARIES NAMES osmosdr
+ PATHS
+ ${LIBOSMOSDR_PKG_LIBRARY_DIRS}
+ /usr/lib
+ /usr/local/lib
+ )
+
+if(LIBOSMOSDR_INCLUDE_DIRS AND LIBOSMOSDR_LIBRARIES)
+ set(LIBOSMOSDR_FOUND TRUE CACHE INTERNAL "libosmosdr found")
+ message(STATUS "Found libosmosdr: ${LIBOSMOSDR_INCLUDE_DIRS}, ${LIBOSMOSDR_LIBRARIES}")
+else(LIBOSMOSDR_INCLUDE_DIRS AND LIBOSMOSDR_LIBRARIES)
+ set(LIBOSMOSDR_FOUND FALSE CACHE INTERNAL "libosmosdr found")
+ message(STATUS "libosmosdr not found.")
+endif(LIBOSMOSDR_INCLUDE_DIRS AND LIBOSMOSDR_LIBRARIES)
+
+mark_as_advanced(LIBOSMOSDR_LIBRARIES LIBOSMOSDR_INCLUDE_DIRS)
+
+endif(NOT LIBOSMOSDR_FOUND)
diff --git a/cmake/Modules/FindLibXTRX.cmake b/cmake/Modules/FindLibXTRX.cmake
deleted file mode 100644
index e7681d1..0000000
--- a/cmake/Modules/FindLibXTRX.cmake
+++ /dev/null
@@ -1,27 +0,0 @@
-if(NOT LIBXTRX_FOUND)
- pkg_check_modules (LIBXTRX_PKG libxtrx)
- find_path(LIBXTRX_INCLUDE_DIRS NAMES xtrx_api.h
- PATHS
- ${LIBXTRX_PKG_INCLUDE_DIRS}
- /usr/include
- /usr/local/include
- )
-
- find_library(LIBXTRX_LIBRARIES NAMES xtrx
- PATHS
- ${LIBXTRX_PKG_LIBRARY_DIRS}
- /usr/lib
- /usr/local/lib
- )
-
-if(LIBXTRX_INCLUDE_DIRS AND LIBXTRX_LIBRARIES)
- set(LIBXTRX_FOUND TRUE CACHE INTERNAL "libxtrx found")
- message(STATUS "Found libxtrx: ${LIBXTRX_INCLUDE_DIRS}, ${LIBXTRX_LIBRARIES}")
-else(LIBXTRX_INCLUDE_DIRS AND LIBXTRX_LIBRARIES)
- set(LIBXTRX_FOUND FALSE CACHE INTERNAL "libxtrx found")
- message(STATUS "libxtrx not found.")
-endif(LIBXTRX_INCLUDE_DIRS AND LIBXTRX_LIBRARIES)
-
-mark_as_advanced(LIBXTRX_LIBRARIES LIBXTRX_INCLUDE_DIRS)
-
-endif(NOT LIBXTRX_FOUND)
diff --git a/cmake/Modules/FindLibbladeRF.cmake b/cmake/Modules/FindLibbladeRF.cmake
index 0971344..fc67082 100644
--- a/cmake/Modules/FindLibbladeRF.cmake
+++ b/cmake/Modules/FindLibbladeRF.cmake
@@ -1,5 +1,9 @@
if(NOT LIBBLADERF_FOUND)
pkg_check_modules (LIBBLADERF_PKG libbladeRF)
+ if (LIBBLADERF_PKG_FOUND AND LIBBLADERF_PKG_VERSION VERSION_LESS "2")
+ message( FATAL_ERROR "Install version 2 or greater of libbladeRF."
+ " Current version ( ${LIBBLADERF_PKG_VERSION} ) is out of date." )
+ endif()
find_path(LIBBLADERF_INCLUDE_DIRS NAMES libbladeRF.h
PATHS
${LIBBLADERF_PKG_INCLUDE_DIRS}
diff --git a/cmake/Modules/GrComponent.cmake b/cmake/Modules/GrComponent.cmake
new file mode 100644
index 0000000..22b0ea4
--- /dev/null
+++ b/cmake/Modules/GrComponent.cmake
@@ -0,0 +1,115 @@
+# Copyright 2010-2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+if(DEFINED __INCLUDED_GR_COMPONENT_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GR_COMPONENT_CMAKE TRUE)
+
+set(_gr_enabled_components "" CACHE INTERNAL "" FORCE)
+set(_gr_disabled_components "" CACHE INTERNAL "" FORCE)
+
+if(NOT DEFINED ENABLE_DEFAULT)
+ set(ENABLE_DEFAULT ON)
+ message(STATUS "")
+ message(STATUS "The build system will automatically enable all components.")
+ message(STATUS "Use -DENABLE_DEFAULT=OFF to disable components by default.")
+endif()
+
+########################################################################
+# Register a component into the system
+# - name: canonical component name
+# - var: variable for enabled status
+# - argn: list of dependencies
+########################################################################
+function(GR_REGISTER_COMPONENT name var)
+ include(CMakeDependentOption)
+ message(STATUS "")
+ message(STATUS "Configuring ${name} support...")
+ foreach(dep ${ARGN})
+ message(STATUS " Dependency ${dep} = ${${dep}}")
+ endforeach(dep)
+
+ #if the user set the var to force, we note this
+ if("${${var}}" STREQUAL "FORCE")
+ set(${var} ON)
+ set(var_force TRUE)
+ else()
+ set(var_force FALSE)
+ endif()
+
+ #rewrite the dependency list so that deps that are also components use the cached version
+ unset(comp_deps)
+ foreach(dep ${ARGN})
+ list(FIND _gr_enabled_components ${dep} dep_enb_index)
+ list(FIND _gr_disabled_components ${dep} dep_dis_index)
+ if (${dep_enb_index} EQUAL -1 AND ${dep_dis_index} EQUAL -1)
+ list(APPEND comp_deps ${dep})
+ else()
+ list(APPEND comp_deps ${dep}_cached) #is a component, use cached version
+ endif()
+ endforeach(dep)
+
+ #setup the dependent option for this component
+ CMAKE_DEPENDENT_OPTION(${var} "enable ${name} support" ${ENABLE_DEFAULT} "${comp_deps}" OFF)
+ set(${var} "${${var}}" PARENT_SCOPE)
+ set(${var}_cached "${${var}}" CACHE INTERNAL "" FORCE)
+
+ #force was specified, but the dependencies were not met
+ if(NOT ${var} AND var_force)
+ message(FATAL_ERROR "user force-enabled ${name} but configuration checked failed")
+ endif()
+
+ #append the component into one of the lists
+ if(${var})
+ message(STATUS " Enabling ${name} support.")
+ list(APPEND _gr_enabled_components ${name})
+ else(${var})
+ message(STATUS " Disabling ${name} support.")
+ list(APPEND _gr_disabled_components ${name})
+ endif(${var})
+ message(STATUS " Override with -D${var}=ON/OFF")
+
+ #make components lists into global variables
+ set(_gr_enabled_components ${_gr_enabled_components} CACHE INTERNAL "" FORCE)
+ set(_gr_disabled_components ${_gr_disabled_components} CACHE INTERNAL "" FORCE)
+endfunction(GR_REGISTER_COMPONENT)
+
+########################################################################
+# Print the registered component summary
+########################################################################
+function(GR_PRINT_COMPONENT_SUMMARY)
+ message(STATUS "")
+ message(STATUS "######################################################")
+ message(STATUS "# gr-osmosdr enabled components ")
+ message(STATUS "######################################################")
+ foreach(comp ${_gr_enabled_components})
+ message(STATUS " * ${comp}")
+ endforeach(comp)
+
+ message(STATUS "")
+ message(STATUS "######################################################")
+ message(STATUS "# gr-osmosdr disabled components ")
+ message(STATUS "######################################################")
+ foreach(comp ${_gr_disabled_components})
+ message(STATUS " * ${comp}")
+ endforeach(comp)
+
+ message(STATUS "")
+endfunction(GR_PRINT_COMPONENT_SUMMARY)
diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake
new file mode 100644
index 0000000..747eb1a
--- /dev/null
+++ b/cmake/Modules/GrMiscUtils.cmake
@@ -0,0 +1,519 @@
+# Copyright 2010-2011,2014 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+if(DEFINED __INCLUDED_GR_MISC_UTILS_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GR_MISC_UTILS_CMAKE TRUE)
+
+########################################################################
+# Set global variable macro.
+# Used for subdirectories to export settings.
+# Example: include and library paths.
+########################################################################
+function(GR_SET_GLOBAL var)
+ set(${var} ${ARGN} CACHE INTERNAL "" FORCE)
+endfunction(GR_SET_GLOBAL)
+
+########################################################################
+# Set the pre-processor definition if the condition is true.
+# - def the pre-processor definition to set and condition name
+########################################################################
+function(GR_ADD_COND_DEF def)
+ if(${def})
+ add_definitions(-D${def})
+ endif(${def})
+endfunction(GR_ADD_COND_DEF)
+
+########################################################################
+# Check for a header and conditionally set a compile define.
+# - hdr the relative path to the header file
+# - def the pre-processor definition to set
+########################################################################
+function(GR_CHECK_HDR_N_DEF hdr def)
+ include(CheckIncludeFileCXX)
+ CHECK_INCLUDE_FILE_CXX(${hdr} ${def})
+ GR_ADD_COND_DEF(${def})
+endfunction(GR_CHECK_HDR_N_DEF)
+
+########################################################################
+# Include subdirectory macro.
+# Sets the CMake directory variables,
+# includes the subdirectory CMakeLists.txt,
+# resets the CMake directory variables.
+#
+# This macro includes subdirectories rather than adding them
+# so that the subdirectory can affect variables in the level above.
+# This provides a work-around for the lack of convenience libraries.
+# This way a subdirectory can append to the list of library sources.
+########################################################################
+macro(GR_INCLUDE_SUBDIRECTORY subdir)
+ #insert the current directories on the front of the list
+ list(INSERT _cmake_source_dirs 0 ${CMAKE_CURRENT_SOURCE_DIR})
+ list(INSERT _cmake_binary_dirs 0 ${CMAKE_CURRENT_BINARY_DIR})
+
+ #set the current directories to the names of the subdirs
+ set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${subdir})
+ set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${subdir})
+
+ #include the subdirectory CMakeLists to run it
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
+
+ #reset the value of the current directories
+ list(GET _cmake_source_dirs 0 CMAKE_CURRENT_SOURCE_DIR)
+ list(GET _cmake_binary_dirs 0 CMAKE_CURRENT_BINARY_DIR)
+
+ #pop the subdir names of the front of the list
+ list(REMOVE_AT _cmake_source_dirs 0)
+ list(REMOVE_AT _cmake_binary_dirs 0)
+endmacro(GR_INCLUDE_SUBDIRECTORY)
+
+########################################################################
+# Check if a compiler flag works and conditionally set a compile define.
+# - flag the compiler flag to check for
+# - have the variable to set with result
+########################################################################
+macro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE flag have)
+ include(CheckCXXCompilerFlag)
+ CHECK_CXX_COMPILER_FLAG(${flag} ${have})
+ if(${have})
+ add_definitions(${flag})
+ endif(${have})
+endmacro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE)
+
+########################################################################
+# Generates the .la libtool file
+# This appears to generate libtool files that cannot be used by auto*.
+# Usage GR_LIBTOOL(TARGET [target] DESTINATION [dest])
+# Notice: there is not COMPONENT option, these will not get distributed.
+########################################################################
+function(GR_LIBTOOL)
+ if(NOT DEFINED GENERATE_LIBTOOL)
+ set(GENERATE_LIBTOOL OFF) #disabled by default
+ endif()
+
+ if(GENERATE_LIBTOOL)
+ include(CMakeParseArgumentsCopy)
+ CMAKE_PARSE_ARGUMENTS(GR_LIBTOOL "" "TARGET;DESTINATION" "" ${ARGN})
+
+ find_program(LIBTOOL libtool)
+ if(LIBTOOL)
+ include(CMakeMacroLibtoolFile)
+ CREATE_LIBTOOL_FILE(${GR_LIBTOOL_TARGET} /${GR_LIBTOOL_DESTINATION})
+ endif(LIBTOOL)
+ endif(GENERATE_LIBTOOL)
+
+endfunction(GR_LIBTOOL)
+
+########################################################################
+# Do standard things to the library target
+# - set target properties
+# - make install rules
+# Also handle gnuradio custom naming conventions w/ extras mode.
+########################################################################
+function(GR_LIBRARY_FOO target)
+ #parse the arguments for component names
+ include(CMakeParseArgumentsCopy)
+ CMAKE_PARSE_ARGUMENTS(GR_LIBRARY "" "RUNTIME_COMPONENT;DEVEL_COMPONENT" "" ${ARGN})
+
+ #set additional target properties
+ set_target_properties(${target} PROPERTIES SOVERSION ${LIBVER})
+
+ #install the generated files like so...
+ install(TARGETS ${target}
+ LIBRARY DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .so/.dylib file
+ ARCHIVE DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_DEVEL_COMPONENT} # .lib file
+ RUNTIME DESTINATION ${GR_RUNTIME_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .dll file
+ )
+
+ #extras mode enabled automatically on linux
+ if(NOT DEFINED LIBRARY_EXTRAS)
+ set(LIBRARY_EXTRAS ${LINUX})
+ endif()
+
+ #special extras mode to enable alternative naming conventions
+ if(LIBRARY_EXTRAS)
+
+ #create .la file before changing props
+ GR_LIBTOOL(TARGET ${target} DESTINATION ${GR_LIBRARY_DIR})
+
+ #give the library a special name with ultra-zero soversion
+ set_target_properties(${target} PROPERTIES OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0")
+ set(target_name lib${target}-${LIBVER}.so.0.0.0)
+
+ #custom command to generate symlinks
+ add_custom_command(
+ TARGET ${target}
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so
+ COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0
+ COMMAND ${CMAKE_COMMAND} -E touch ${target_name} #so the symlinks point to something valid so cmake 2.6 will install
+ )
+
+ #and install the extra symlinks
+ install(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so
+ ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0
+ DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT}
+ )
+
+ endif(LIBRARY_EXTRAS)
+endfunction(GR_LIBRARY_FOO)
+
+########################################################################
+# Create a dummy custom command that depends on other targets.
+# Usage:
+# GR_GEN_TARGET_DEPS(unique_name target_deps <target1> <target2> ...)
+# ADD_CUSTOM_COMMAND(<the usual args> ${target_deps})
+#
+# Custom command cant depend on targets, but can depend on executables,
+# and executables can depend on targets. So this is the process:
+########################################################################
+function(GR_GEN_TARGET_DEPS name var)
+ file(
+ WRITE ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in
+ "int main(void){return 0;}\n"
+ )
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp
+ )
+ add_executable(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp)
+ if(ARGN)
+ add_dependencies(${name} ${ARGN})
+ endif(ARGN)
+
+ if(CMAKE_CROSSCOMPILING)
+ set(${var} "DEPENDS;${name}" PARENT_SCOPE) #cant call command when cross
+ else()
+ set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE)
+ endif()
+endfunction(GR_GEN_TARGET_DEPS)
+
+########################################################################
+# Control use of gr_logger
+# Usage:
+# GR_LOGGING()
+#
+# Will set ENABLE_GR_LOG to 1 by default.
+# Can manually set with -DENABLE_GR_LOG=0|1
+########################################################################
+function(GR_LOGGING)
+ find_package(Log4cpp)
+
+ OPTION(ENABLE_GR_LOG "Use gr_logger" ON)
+ if(ENABLE_GR_LOG)
+ # If gr_logger is enabled, make it usable
+ add_definitions( -DENABLE_GR_LOG )
+
+ # also test LOG4CPP; if we have it, use this version of the logger
+ # otherwise, default to the stdout/stderr model.
+ if(LOG4CPP_FOUND)
+ SET(HAVE_LOG4CPP True CACHE INTERNAL "" FORCE)
+ add_definitions( -DHAVE_LOG4CPP )
+ else(not LOG4CPP_FOUND)
+ SET(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE)
+ SET(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE)
+ SET(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE)
+ SET(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE)
+ endif(LOG4CPP_FOUND)
+
+ SET(ENABLE_GR_LOG ${ENABLE_GR_LOG} CACHE INTERNAL "" FORCE)
+
+ else(ENABLE_GR_LOG)
+ SET(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE)
+ SET(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE)
+ SET(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE)
+ SET(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE)
+ endif(ENABLE_GR_LOG)
+
+ message(STATUS "ENABLE_GR_LOG set to ${ENABLE_GR_LOG}.")
+ message(STATUS "HAVE_LOG4CPP set to ${HAVE_LOG4CPP}.")
+ message(STATUS "LOG4CPP_LIBRARIES set to ${LOG4CPP_LIBRARIES}.")
+
+endfunction(GR_LOGGING)
+
+########################################################################
+# Run GRCC to compile .grc files into .py files.
+#
+# Usage: GRCC(filename, directory)
+# - filenames: List of file name of .grc file
+# - directory: directory of built .py file - usually in
+# ${CMAKE_CURRENT_BINARY_DIR}
+# - Sets PYFILES: output converted GRC file names to Python files.
+########################################################################
+function(GRCC)
+ # Extract directory from list of args, remove it for the list of filenames.
+ list(GET ARGV -1 directory)
+ list(REMOVE_AT ARGV -1)
+ set(filenames ${ARGV})
+ file(MAKE_DIRECTORY ${directory})
+
+ SET(GRCC_COMMAND ${CMAKE_SOURCE_DIR}/gr-utils/python/grcc)
+
+ # GRCC uses some stuff in grc and gnuradio-runtime, so we force
+ # the known paths here
+ list(APPEND PYTHONPATHS
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/gnuradio-runtime/python
+ ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/swig
+ ${CMAKE_BINARY_DIR}/gnuradio-runtime/lib/swig
+ )
+
+ if(WIN32)
+ #SWIG generates the python library files into a subdirectory.
+ #Therefore, we must append this subdirectory into PYTHONPATH.
+ #Only do this for the python directories matching the following:
+ foreach(pydir ${PYTHONPATHS})
+ get_filename_component(name ${pydir} NAME)
+ if(name MATCHES "^(swig|lib|src)$")
+ list(APPEND PYTHONPATHS ${pydir}/${CMAKE_BUILD_TYPE})
+ endif()
+ endforeach(pydir)
+ endif(WIN32)
+
+ file(TO_NATIVE_PATH "${PYTHONPATHS}" pypath)
+
+ if(UNIX)
+ list(APPEND pypath "$PYTHONPATH")
+ string(REPLACE ";" ":" pypath "${pypath}")
+ set(ENV{PYTHONPATH} ${pypath})
+ endif(UNIX)
+
+ if(WIN32)
+ list(APPEND pypath "%PYTHONPATH%")
+ string(REPLACE ";" "\\;" pypath "${pypath}")
+ #list(APPEND environs "PYTHONPATH=${pypath}")
+ set(ENV{PYTHONPATH} ${pypath})
+ endif(WIN32)
+
+ foreach(f ${filenames})
+ execute_process(
+ COMMAND ${GRCC_COMMAND} -d ${directory} ${f}
+ )
+ string(REPLACE ".grc" ".py" pyfile "${f}")
+ string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" pyfile "${pyfile}")
+ list(APPEND pyfiles ${pyfile})
+ endforeach(f)
+
+ set(PYFILES ${pyfiles} PARENT_SCOPE)
+endfunction(GRCC)
+
+########################################################################
+# Check if HAVE_PTHREAD_SETSCHEDPARAM and HAVE_SCHED_SETSCHEDULER
+# should be defined
+########################################################################
+macro(GR_CHECK_LINUX_SCHED_AVAIL)
+set(CMAKE_REQUIRED_LIBRARIES -lpthread)
+ CHECK_CXX_SOURCE_COMPILES("
+ #include <pthread.h>
+ int main(){
+ pthread_t pthread;
+ pthread_setschedparam(pthread, 0, 0);
+ return 0;
+ } " HAVE_PTHREAD_SETSCHEDPARAM
+ )
+ GR_ADD_COND_DEF(HAVE_PTHREAD_SETSCHEDPARAM)
+
+ CHECK_CXX_SOURCE_COMPILES("
+ #include <sched.h>
+ int main(){
+ pid_t pid;
+ sched_setscheduler(pid, 0, 0);
+ return 0;
+ } " HAVE_SCHED_SETSCHEDULER
+ )
+ GR_ADD_COND_DEF(HAVE_SCHED_SETSCHEDULER)
+endmacro(GR_CHECK_LINUX_SCHED_AVAIL)
+
+########################################################################
+# Macros to generate source and header files from template
+########################################################################
+macro(GR_EXPAND_X_H component root)
+
+ include(GrPython)
+
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+"#!${PYTHON_EXECUTABLE}
+
+import sys, os, re
+sys.path.append('${GR_RUNTIME_PYTHONPATH}')
+os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
+os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
+
+if __name__ == '__main__':
+ import build_utils
+ root, inp = sys.argv[1:3]
+ for sig in sys.argv[3:]:
+ name = re.sub ('X+', sig, root)
+ d = build_utils.standard_dict2(name, sig, '${component}')
+ build_utils.expand_template(d, inp)
+")
+
+ #make a list of all the generated headers
+ unset(expanded_files_h)
+ foreach(sig ${ARGN})
+ string(REGEX REPLACE "X+" ${sig} name ${root})
+ list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
+ endforeach(sig)
+ unset(name)
+
+ #create a command to generate the headers
+ add_custom_command(
+ OUTPUT ${expanded_files_h}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.h.t ${ARGN}
+ )
+
+ #install rules for the generated headers
+ list(APPEND generated_includes ${expanded_files_h})
+
+endmacro(GR_EXPAND_X_H)
+
+macro(GR_EXPAND_X_CC_H component root)
+
+ include(GrPython)
+
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+"#!${PYTHON_EXECUTABLE}
+
+import sys, os, re
+sys.path.append('${GR_RUNTIME_PYTHONPATH}')
+os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
+os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
+
+if __name__ == '__main__':
+ import build_utils
+ root, inp = sys.argv[1:3]
+ for sig in sys.argv[3:]:
+ name = re.sub ('X+', sig, root)
+ d = build_utils.standard_impl_dict2(name, sig, '${component}')
+ build_utils.expand_template(d, inp)
+")
+
+ #make a list of all the generated files
+ unset(expanded_files_cc)
+ unset(expanded_files_h)
+ foreach(sig ${ARGN})
+ string(REGEX REPLACE "X+" ${sig} name ${root})
+ list(APPEND expanded_files_cc ${CMAKE_CURRENT_BINARY_DIR}/${name}.cc)
+ list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
+ endforeach(sig)
+ unset(name)
+
+ #create a command to generate the source files
+ add_custom_command(
+ OUTPUT ${expanded_files_cc}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.cc.t ${ARGN}
+ )
+
+ #create a command to generate the header files
+ add_custom_command(
+ OUTPUT ${expanded_files_h}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.h.t ${ARGN}
+ )
+
+ #make source files depends on headers to force generation
+ set_source_files_properties(${expanded_files_cc}
+ PROPERTIES OBJECT_DEPENDS "${expanded_files_h}"
+ )
+
+ #install rules for the generated files
+ list(APPEND generated_sources ${expanded_files_cc})
+ list(APPEND generated_headers ${expanded_files_h})
+
+endmacro(GR_EXPAND_X_CC_H)
+
+macro(GR_EXPAND_X_CC_H_IMPL component root)
+
+ include(GrPython)
+
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+"#!${PYTHON_EXECUTABLE}
+
+import sys, os, re
+sys.path.append('${GR_RUNTIME_PYTHONPATH}')
+os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
+os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
+
+if __name__ == '__main__':
+ import build_utils
+ root, inp = sys.argv[1:3]
+ for sig in sys.argv[3:]:
+ name = re.sub ('X+', sig, root)
+ d = build_utils.standard_dict(name, sig, '${component}')
+ build_utils.expand_template(d, inp, '_impl')
+")
+
+ #make a list of all the generated files
+ unset(expanded_files_cc_impl)
+ unset(expanded_files_h_impl)
+ unset(expanded_files_h)
+ foreach(sig ${ARGN})
+ string(REGEX REPLACE "X+" ${sig} name ${root})
+ list(APPEND expanded_files_cc_impl ${CMAKE_CURRENT_BINARY_DIR}/${name}_impl.cc)
+ list(APPEND expanded_files_h_impl ${CMAKE_CURRENT_BINARY_DIR}/${name}_impl.h)
+ list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/../include/gnuradio/${component}/${name}.h)
+ endforeach(sig)
+ unset(name)
+
+ #create a command to generate the _impl.cc files
+ add_custom_command(
+ OUTPUT ${expanded_files_cc_impl}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.cc.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}_impl.cc.t ${ARGN}
+ )
+
+ #create a command to generate the _impl.h files
+ add_custom_command(
+ OUTPUT ${expanded_files_h_impl}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.h.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}_impl.h.t ${ARGN}
+ )
+
+ #make _impl.cc source files depend on _impl.h to force generation
+ set_source_files_properties(${expanded_files_cc_impl}
+ PROPERTIES OBJECT_DEPENDS "${expanded_files_h_impl}"
+ )
+
+ #make _impl.h source files depend on headers to force generation
+ set_source_files_properties(${expanded_files_h_impl}
+ PROPERTIES OBJECT_DEPENDS "${expanded_files_h}"
+ )
+
+ #install rules for the generated files
+ list(APPEND generated_sources ${expanded_files_cc_impl})
+ list(APPEND generated_headers ${expanded_files_h_impl})
+
+endmacro(GR_EXPAND_X_CC_H_IMPL)
diff --git a/cmake/Modules/GrPlatform.cmake b/cmake/Modules/GrPlatform.cmake
new file mode 100644
index 0000000..fbbea5f
--- /dev/null
+++ b/cmake/Modules/GrPlatform.cmake
@@ -0,0 +1,54 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+if(DEFINED __INCLUDED_GR_PLATFORM_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GR_PLATFORM_CMAKE TRUE)
+
+########################################################################
+# Setup additional defines for OS types
+########################################################################
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(LINUX TRUE)
+endif()
+
+if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/debian_version")
+ set(DEBIAN TRUE)
+endif()
+
+if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/redhat-release")
+ set(REDHAT TRUE)
+endif()
+
+if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/slackware-version")
+ set(SLACKWARE TRUE)
+endif()
+
+########################################################################
+# when the library suffix should be 64 (applies to redhat linux family)
+########################################################################
+if (REDHAT OR SLACKWARE)
+ set(LIB64_CONVENTION TRUE)
+endif()
+
+if(NOT DEFINED LIB_SUFFIX AND LIB64_CONVENTION AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$")
+ set(LIB_SUFFIX 64)
+endif()
+set(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix")
diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake
new file mode 100644
index 0000000..395faff
--- /dev/null
+++ b/cmake/Modules/GrPython.cmake
@@ -0,0 +1,242 @@
+# Copyright 2010-2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+if(DEFINED __INCLUDED_GR_PYTHON_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GR_PYTHON_CMAKE TRUE)
+
+########################################################################
+# Setup the python interpreter:
+# This allows the user to specify a specific interpreter,
+# or finds the interpreter via the built-in cmake module.
+########################################################################
+#this allows the user to override PYTHON_EXECUTABLE
+if(PYTHON_EXECUTABLE)
+
+ set(PYTHONINTERP_FOUND TRUE)
+
+#otherwise if not set, try to automatically find it
+else(PYTHON_EXECUTABLE)
+
+ #use the built-in find script
+ find_package(PythonInterp 2)
+
+ #and if that fails use the find program routine
+ if(NOT PYTHONINTERP_FOUND)
+ find_program(PYTHON_EXECUTABLE NAMES python python2 python2.7 python2.6 python2.5)
+ if(PYTHON_EXECUTABLE)
+ set(PYTHONINTERP_FOUND TRUE)
+ endif(PYTHON_EXECUTABLE)
+ endif(NOT PYTHONINTERP_FOUND)
+
+endif(PYTHON_EXECUTABLE)
+
+if (CMAKE_CROSSCOMPILING)
+ set(QA_PYTHON_EXECUTABLE "/usr/bin/python")
+else (CMAKE_CROSSCOMPILING)
+ set(QA_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE})
+endif(CMAKE_CROSSCOMPILING)
+
+#make the path to the executable appear in the cmake gui
+set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter")
+set(QA_PYTHON_EXECUTABLE ${QA_PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter for QA tests")
+
+#make sure we can use -B with python (introduced in 2.6)
+if(PYTHON_EXECUTABLE)
+ execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -B -c ""
+ OUTPUT_QUIET ERROR_QUIET
+ RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT
+ )
+ if(PYTHON_HAS_DASH_B_RESULT EQUAL 0)
+ set(PYTHON_DASH_B "-B")
+ endif()
+endif(PYTHON_EXECUTABLE)
+
+########################################################################
+# Check for the existence of a python module:
+# - desc a string description of the check
+# - mod the name of the module to import
+# - cmd an additional command to run
+# - have the result variable to set
+########################################################################
+macro(GR_PYTHON_CHECK_MODULE desc mod cmd have)
+ message(STATUS "")
+ message(STATUS "Python checking for ${desc}")
+ execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -c "
+#########################################
+try:
+ import ${mod}
+ assert ${cmd}
+except ImportError, AssertionError: exit(-1)
+except: pass
+#########################################"
+ RESULT_VARIABLE ${have}
+ )
+ if(${have} EQUAL 0)
+ message(STATUS "Python checking for ${desc} - found")
+ set(${have} TRUE)
+ else(${have} EQUAL 0)
+ message(STATUS "Python checking for ${desc} - not found")
+ set(${have} FALSE)
+ endif(${have} EQUAL 0)
+endmacro(GR_PYTHON_CHECK_MODULE)
+
+########################################################################
+# Sets the python installation directory GR_PYTHON_DIR
+########################################################################
+if(NOT DEFINED GR_PYTHON_DIR)
+execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "
+from distutils import sysconfig
+print sysconfig.get_python_lib(plat_specific=True, prefix='')
+" OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+endif()
+file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR)
+
+########################################################################
+# Create an always-built target with a unique name
+# Usage: GR_UNIQUE_TARGET(<description> <dependencies list>)
+########################################################################
+function(GR_UNIQUE_TARGET desc)
+ file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib
+unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5]
+print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))"
+ OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE)
+ add_custom_target(${_target} ALL DEPENDS ${ARGN})
+endfunction(GR_UNIQUE_TARGET)
+
+########################################################################
+# Install python sources (also builds and installs byte-compiled python)
+########################################################################
+function(GR_PYTHON_INSTALL)
+ include(CMakeParseArgumentsCopy)
+ CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN})
+
+ ####################################################################
+ if(GR_PYTHON_INSTALL_FILES)
+ ####################################################################
+ install(${ARGN}) #installs regular python files
+
+ #create a list of all generated files
+ unset(pysrcfiles)
+ unset(pycfiles)
+ unset(pyofiles)
+ foreach(pyfile ${GR_PYTHON_INSTALL_FILES})
+ get_filename_component(pyfile ${pyfile} ABSOLUTE)
+ list(APPEND pysrcfiles ${pyfile})
+
+ #determine if this file is in the source or binary directory
+ file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile})
+ string(LENGTH "${source_rel_path}" source_rel_path_len)
+ file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile})
+ string(LENGTH "${binary_rel_path}" binary_rel_path_len)
+
+ #and set the generated path appropriately
+ if(${source_rel_path_len} GREATER ${binary_rel_path_len})
+ set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path})
+ else()
+ set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path})
+ endif()
+ list(APPEND pycfiles ${pygenfile}c)
+ list(APPEND pyofiles ${pygenfile}o)
+
+ #ensure generation path exists
+ get_filename_component(pygen_path ${pygenfile} PATH)
+ file(MAKE_DIRECTORY ${pygen_path})
+
+ endforeach(pyfile)
+
+ #the command to generate the pyc files
+ add_custom_command(
+ DEPENDS ${pysrcfiles} OUTPUT ${pycfiles}
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles}
+ )
+
+ #the command to generate the pyo files
+ add_custom_command(
+ DEPENDS ${pysrcfiles} OUTPUT ${pyofiles}
+ COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles}
+ )
+
+ #create install rule and add generated files to target list
+ set(python_install_gen_targets ${pycfiles} ${pyofiles})
+ install(FILES ${python_install_gen_targets}
+ DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
+ COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
+ )
+
+
+ ####################################################################
+ elseif(GR_PYTHON_INSTALL_PROGRAMS)
+ ####################################################################
+ file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native)
+
+ if (CMAKE_CROSSCOMPILING)
+ set(pyexe_native "/usr/bin/env python")
+ endif()
+
+ foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS})
+ get_filename_component(pyfile_name ${pyfile} NAME)
+ get_filename_component(pyfile ${pyfile} ABSOLUTE)
+ string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe")
+ list(APPEND python_install_gen_targets ${pyexefile})
+
+ get_filename_component(pyexefile_path ${pyexefile} PATH)
+ file(MAKE_DIRECTORY ${pyexefile_path})
+
+ add_custom_command(
+ OUTPUT ${pyexefile} DEPENDS ${pyfile}
+ COMMAND ${PYTHON_EXECUTABLE} -c
+ "open('${pyexefile}','w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())"
+ COMMENT "Shebangin ${pyfile_name}"
+ VERBATIM
+ )
+
+ #on windows, python files need an extension to execute
+ get_filename_component(pyfile_ext ${pyfile} EXT)
+ if(WIN32 AND NOT pyfile_ext)
+ set(pyfile_name "${pyfile_name}.py")
+ endif()
+
+ install(PROGRAMS ${pyexefile} RENAME ${pyfile_name}
+ DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
+ COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
+ )
+ endforeach(pyfile)
+
+ endif()
+
+ GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets})
+
+endfunction(GR_PYTHON_INSTALL)
+
+########################################################################
+# Write the python helper script that generates byte code files
+########################################################################
+file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py "
+import sys, py_compile
+files = sys.argv[1:]
+srcs, gens = files[:len(files)/2], files[len(files)/2:]
+for src, gen in zip(srcs, gens):
+ py_compile.compile(file=src, cfile=gen, doraise=True)
+")
diff --git a/cmake/Modules/GrTest.cmake b/cmake/Modules/GrTest.cmake
new file mode 100644
index 0000000..62caab4
--- /dev/null
+++ b/cmake/Modules/GrTest.cmake
@@ -0,0 +1,143 @@
+# Copyright 2010-2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+if(DEFINED __INCLUDED_GR_TEST_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GR_TEST_CMAKE TRUE)
+
+########################################################################
+# Add a unit test and setup the environment for a unit test.
+# Takes the same arguments as the ADD_TEST function.
+#
+# Before calling set the following variables:
+# GR_TEST_TARGET_DEPS - built targets for the library path
+# GR_TEST_LIBRARY_DIRS - directories for the library path
+# GR_TEST_PYTHON_DIRS - directories for the python path
+# GR_TEST_ENVIRONS - other environment key/value pairs
+########################################################################
+function(GR_ADD_TEST test_name)
+
+ #Ensure that the build exe also appears in the PATH.
+ list(APPEND GR_TEST_TARGET_DEPS ${ARGN})
+
+ #In the land of windows, all libraries must be in the PATH.
+ #Since the dependent libraries are not yet installed,
+ #we must manually set them in the PATH to run tests.
+ #The following appends the path of a target dependency.
+ foreach(target ${GR_TEST_TARGET_DEPS})
+ get_target_property(location ${target} LOCATION)
+ if(location)
+ get_filename_component(path ${location} PATH)
+ string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path})
+ list(APPEND GR_TEST_LIBRARY_DIRS ${path})
+ endif(location)
+ endforeach(target)
+
+ if(WIN32)
+ #SWIG generates the python library files into a subdirectory.
+ #Therefore, we must append this subdirectory into PYTHONPATH.
+ #Only do this for the python directories matching the following:
+ foreach(pydir ${GR_TEST_PYTHON_DIRS})
+ get_filename_component(name ${pydir} NAME)
+ if(name MATCHES "^(swig|lib|src)$")
+ list(APPEND GR_TEST_PYTHON_DIRS ${pydir}/${CMAKE_BUILD_TYPE})
+ endif()
+ endforeach(pydir)
+ endif(WIN32)
+
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} srcdir)
+ file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list?
+ file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list?
+
+ set(environs "VOLK_GENERIC=1" "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}")
+ list(APPEND environs ${GR_TEST_ENVIRONS})
+
+ #http://www.cmake.org/pipermail/cmake/2009-May/029464.html
+ #Replaced this add test + set environs code with the shell script generation.
+ #Its nicer to be able to manually run the shell script to diagnose problems.
+ #ADD_TEST(${ARGV})
+ #SET_TESTS_PROPERTIES(${test_name} PROPERTIES ENVIRONMENT "${environs}")
+
+ if(UNIX)
+ set(LD_PATH_VAR "LD_LIBRARY_PATH")
+ if(APPLE)
+ set(LD_PATH_VAR "DYLD_LIBRARY_PATH")
+ endif()
+
+ set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH")
+ list(APPEND libpath "$${LD_PATH_VAR}")
+ list(APPEND pypath "$PYTHONPATH")
+
+ #replace list separator with the path separator
+ string(REPLACE ";" ":" libpath "${libpath}")
+ string(REPLACE ";" ":" pypath "${pypath}")
+ list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}")
+
+ #generate a bat file that sets the environment and runs the test
+ if (CMAKE_CROSSCOMPILING)
+ set(SHELL "/bin/sh")
+ else(CMAKE_CROSSCOMPILING)
+ find_program(SHELL sh)
+ endif(CMAKE_CROSSCOMPILING)
+ set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh)
+ file(WRITE ${sh_file} "#!${SHELL}\n")
+ #each line sets an environment variable
+ foreach(environ ${environs})
+ file(APPEND ${sh_file} "export ${environ}\n")
+ endforeach(environ)
+ #load the command to run with its arguments
+ foreach(arg ${ARGN})
+ file(APPEND ${sh_file} "${arg} ")
+ endforeach(arg)
+ file(APPEND ${sh_file} "\n")
+
+ #make the shell file executable
+ execute_process(COMMAND chmod +x ${sh_file})
+
+ add_test(${test_name} ${SHELL} ${sh_file})
+
+ endif(UNIX)
+
+ if(WIN32)
+ list(APPEND libpath ${DLL_PATHS} "%PATH%")
+ list(APPEND pypath "%PYTHONPATH%")
+
+ #replace list separator with the path separator (escaped)
+ string(REPLACE ";" "\\;" libpath "${libpath}")
+ string(REPLACE ";" "\\;" pypath "${pypath}")
+ list(APPEND environs "PATH=${libpath}" "PYTHONPATH=${pypath}")
+
+ #generate a bat file that sets the environment and runs the test
+ set(bat_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.bat)
+ file(WRITE ${bat_file} "@echo off\n")
+ #each line sets an environment variable
+ foreach(environ ${environs})
+ file(APPEND ${bat_file} "SET ${environ}\n")
+ endforeach(environ)
+ #load the command to run with its arguments
+ foreach(arg ${ARGN})
+ file(APPEND ${bat_file} "${arg} ")
+ endforeach(arg)
+ file(APPEND ${bat_file} "\n")
+
+ add_test(${test_name} ${bat_file})
+ endif(WIN32)
+
+endfunction(GR_ADD_TEST)
diff --git a/cmake/Modules/GrVersion.cmake b/cmake/Modules/GrVersion.cmake
new file mode 100644
index 0000000..bafd0a7
--- /dev/null
+++ b/cmake/Modules/GrVersion.cmake
@@ -0,0 +1,82 @@
+# Copyright 2011,2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+if(DEFINED __INCLUDED_GR_VERSION_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GR_VERSION_CMAKE TRUE)
+
+#eventually, replace version.sh and fill in the variables below
+set(MAJOR_VERSION ${VERSION_INFO_MAJOR_VERSION})
+set(API_COMPAT ${VERSION_INFO_API_COMPAT})
+set(MINOR_VERSION ${VERSION_INFO_MINOR_VERSION})
+set(MAINT_VERSION ${VERSION_INFO_MAINT_VERSION})
+
+########################################################################
+# Extract the version string from git describe.
+########################################################################
+find_package(Git)
+
+if(GIT_FOUND AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
+ message(STATUS "Extracting version information from git describe...")
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} describe --always --abbrev=8 --long
+ OUTPUT_VARIABLE GIT_DESCRIBE OUTPUT_STRIP_TRAILING_WHITESPACE
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+else()
+ set(GIT_DESCRIBE "v${MAJOR_VERSION}.${API_COMPAT}.x-xxx-xunknown")
+endif()
+
+########################################################################
+# Use the logic below to set the version constants
+########################################################################
+if("${MINOR_VERSION}" STREQUAL "git")
+ # VERSION: 3.3git-xxx-gxxxxxxxx
+ # DOCVER: 3.3git
+ # LIBVER: 3.3git
+ set(VERSION "${GIT_DESCRIBE}")
+ set(DOCVER "${MAJOR_VERSION}.${API_COMPAT}${MINOR_VERSION}")
+ set(LIBVER "${MAJOR_VERSION}.${API_COMPAT}${MINOR_VERSION}")
+ set(RC_MINOR_VERSION "0")
+ set(RC_MAINT_VERSION "0")
+elseif("${MAINT_VERSION}" STREQUAL "git")
+ # VERSION: 3.3.1git-xxx-gxxxxxxxx
+ # DOCVER: 3.3.1git
+ # LIBVER: 3.3.1git
+ set(VERSION "${GIT_DESCRIBE}")
+ set(DOCVER "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}${MAINT_VERSION}")
+ set(LIBVER "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}${MAINT_VERSION}")
+ math(EXPR RC_MINOR_VERSION "${MINOR_VERSION} - 1")
+ set(RC_MAINT_VERSION "0")
+else()
+ # This is a numbered release.
+ # VERSION: 3.3.1{.x}
+ # DOCVER: 3.3.1{.x}
+ # LIBVER: 3.3.1{.x}
+ if("${MAINT_VERSION}" STREQUAL "0")
+ set(VERSION "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}")
+ else()
+ set(VERSION "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}.${MAINT_VERSION}")
+ endif()
+ set(DOCVER "${VERSION}")
+ set(LIBVER "${VERSION}")
+ set(RC_MINOR_VERSION ${MINOR_VERSION})
+ set(RC_MAINT_VERSION ${MAINT_VERSION})
+endif()
diff --git a/cmake/Modules/OsmoSDRMiscUtils.cmake b/cmake/Modules/OsmoSDRMiscUtils.cmake
new file mode 100644
index 0000000..21c6351
--- /dev/null
+++ b/cmake/Modules/OsmoSDRMiscUtils.cmake
@@ -0,0 +1,132 @@
+# Copyright 2010-2011,2014 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+if(DEFINED __INCLUDED_OSMOSDR_MISC_UTILS_CMAKE)
+ return()
+endif()
+set(__INCLUDED_OSMOSDR_MISC_UTILS_CMAKE TRUE)
+
+########################################################################
+# This macro includes subdirectories rather than adding them
+# so that the subdirectory can affect variables in the level above.
+# This provides a work-around for the lack of convenience libraries.
+# This way a subdirectory can append to the list of library sources.
+########################################################################
+macro(GR_INCLUDE_SUBDIRECTORY subdir)
+ #insert the current directories on the front of the list
+ list(INSERT _cmake_source_dirs 0 ${CMAKE_CURRENT_SOURCE_DIR})
+ list(INSERT _cmake_binary_dirs 0 ${CMAKE_CURRENT_BINARY_DIR})
+
+ #set the current directories to the names of the subdirs
+ set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${subdir})
+ set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${subdir})
+
+ #include the subdirectory CMakeLists to run it
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
+
+ #reset the value of the current directories
+ list(GET _cmake_source_dirs 0 CMAKE_CURRENT_SOURCE_DIR)
+ list(GET _cmake_binary_dirs 0 CMAKE_CURRENT_BINARY_DIR)
+
+ #pop the subdir names of the front of the list
+ list(REMOVE_AT _cmake_source_dirs 0)
+ list(REMOVE_AT _cmake_binary_dirs 0)
+endmacro(GR_INCLUDE_SUBDIRECTORY)
+
+
+########################################################################
+# Generates the .la libtool file
+# This appears to generate libtool files that cannot be used by auto*.
+# Usage GR_LIBTOOL(TARGET [target] DESTINATION [dest])
+# Notice: there is not COMPONENT option, these will not get distributed.
+########################################################################
+function(GR_LIBTOOL)
+ if(NOT DEFINED GENERATE_LIBTOOL)
+ set(GENERATE_LIBTOOL OFF) #disabled by default
+ endif()
+
+ if(GENERATE_LIBTOOL)
+ include(CMakeParseArgumentsCopy)
+ CMAKE_PARSE_ARGUMENTS(GR_LIBTOOL "" "TARGET;DESTINATION" "" ${ARGN})
+
+ find_program(LIBTOOL libtool)
+ if(LIBTOOL)
+ include(CMakeMacroLibtoolFile)
+ CREATE_LIBTOOL_FILE(${GR_LIBTOOL_TARGET} /${GR_LIBTOOL_DESTINATION})
+ endif(LIBTOOL)
+ endif(GENERATE_LIBTOOL)
+
+endfunction(GR_LIBTOOL)
+
+########################################################################
+# Do standard things to the library target
+# - set target properties
+# - make install rules
+# Also handle gnuradio custom naming conventions w/ extras mode.
+########################################################################
+function(GR_LIBRARY_FOO_V2 target)
+ #parse the arguments for component names
+ include(CMakeParseArgumentsCopy)
+ CMAKE_PARSE_ARGUMENTS(GR_LIBRARY "" "RUNTIME_COMPONENT;DEVEL_COMPONENT" "" ${ARGN})
+
+ #set additional target properties
+ set_target_properties(${target} PROPERTIES SOVERSION ${LIBVER})
+
+ #install the generated files like so...
+ install(TARGETS ${target}
+ LIBRARY DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .so/.dylib file
+ ARCHIVE DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_DEVEL_COMPONENT} # .lib file
+ RUNTIME DESTINATION ${GR_RUNTIME_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .dll file
+ )
+
+ #extras mode enabled automatically on linux
+ if(NOT DEFINED LIBRARY_EXTRAS)
+ set(LIBRARY_EXTRAS ${LINUX})
+ endif()
+
+ #special extras mode to enable alternative naming conventions
+ if(LIBRARY_EXTRAS)
+
+ #create .la file before changing props
+ GR_LIBTOOL(TARGET ${target} DESTINATION ${GR_LIBRARY_DIR})
+
+ #give the library a special name with ultra-zero soversion
+ set_target_properties(${target} PROPERTIES OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0")
+ set(target_name lib${target}-${LIBVER}.so.0.0.0)
+
+ #custom command to generate symlinks
+ add_custom_command(
+ TARGET ${target}
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so
+ COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0
+ COMMAND ${CMAKE_COMMAND} -E touch ${target_name} #so the symlinks point to something valid so cmake 2.6 will install
+ )
+
+ #and install the extra symlinks
+ install(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so
+ ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0
+ DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT}
+ )
+
+ endif(LIBRARY_EXTRAS)
+endfunction(GR_LIBRARY_FOO_V2)
diff --git a/cmake/Modules/osmosdrConfig.cmake b/cmake/Modules/osmosdrConfig.cmake
new file mode 100644
index 0000000..a3b341a
--- /dev/null
+++ b/cmake/Modules/osmosdrConfig.cmake
@@ -0,0 +1,31 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_OSMOSDR osmosdr)
+
+FIND_PATH(
+ OSMOSDR_INCLUDE_DIRS
+ NAMES osmosdr/api.h
+ HINTS $ENV{OSMOSDR_DIR}/include
+ ${PC_OSMOSDR_INCLUDEDIR}
+ PATHS ${CMAKE_INSTALL_PREFIX}/include
+ /usr/local/include
+ /usr/include
+)
+
+FIND_LIBRARY(
+ OSMOSDR_LIBRARIES
+ NAMES gnuradio-osmosdr
+ HINTS $ENV{OSMOSDR_DIR}/lib
+ ${PC_OSMOSDR_LIBDIR}
+ PATHS ${CMAKE_INSTALL_PREFIX}/lib
+ ${CMAKE_INSTALL_PREFIX}/lib64
+ /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+ )
+
+include("${CMAKE_CURRENT_LIST_DIR}/osmosdrTarget.cmake")
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OSMOSDR DEFAULT_MSG OSMOSDR_LIBRARIES OSMOSDR_INCLUDE_DIRS)
+MARK_AS_ADVANCED(OSMOSDR_LIBRARIES OSMOSDR_INCLUDE_DIRS)
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index aa620b4..a50dbf8 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -1,23 +1,29 @@
# Copyright 2011 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file was generated by gr_modtool, a tool from the GNU Radio framework
+# This file is a part of gr-osmosdr
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
########################################################################
+# Setup dependencies
+########################################################################
+find_package(Doxygen)
+
+########################################################################
# Begin conditional configuration
########################################################################
if(ENABLE_DOXYGEN)
diff --git a/docs/doxygen/Doxyfile.in b/docs/doxygen/Doxyfile.in
index db80050..ab27c33 100644
--- a/docs/doxygen/Doxyfile.in
+++ b/docs/doxygen/Doxyfile.in
@@ -28,7 +28,7 @@ DOXYFILE_ENCODING = UTF-8
# identify the project. Note that if you do not use Doxywizard you need
# to put quotes around the project name if it contains spaces.
-PROJECT_NAME = "GNU Radio's TEST Package"
+PROJECT_NAME = "GNU Radio's OSMOSDR Package"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
@@ -654,8 +654,8 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = "@top_srcdir@" \
- "@top_builddir@"
+INPUT = @top_srcdir@ \
+ @top_builddir@
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -790,7 +790,7 @@ INPUT_FILTER =
# info on how filters are used. If FILTER_PATTERNS is empty or if
# non of the patterns match the file name, INPUT_FILTER is applied.
-FILTER_PATTERNS = *.py="@top_srcdir@"/doc/doxygen/other/doxypy.py
+FILTER_PATTERNS = *.py=@top_srcdir@/doc/doxygen/other/doxypy.py
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
diff --git a/docs/doxygen/Doxyfile.swig_doc.in b/docs/doxygen/Doxyfile.swig_doc.in
index cbe06d6..33bc2af 100644
--- a/docs/doxygen/Doxyfile.swig_doc.in
+++ b/docs/doxygen/Doxyfile.swig_doc.in
@@ -54,7 +54,7 @@ PROJECT_LOGO =
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
-OUTPUT_DIRECTORY = "@OUTPUT_DIRECTORY@"
+OUTPUT_DIRECTORY = @OUTPUT_DIRECTORY@
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
diff --git a/docs/doxygen/other/group_defs.dox b/docs/doxygen/other/group_defs.dox
index 174edeb..03f00c0 100644
--- a/docs/doxygen/other/group_defs.dox
+++ b/docs/doxygen/other/group_defs.dox
@@ -1,6 +1,6 @@
/*!
- * \defgroup block GNU Radio TEST C++ Signal Processing Blocks
- * \brief All C++ blocks that can be used from the TEST GNU Radio
+ * \defgroup block GNU Radio OSMOSDR C++ Signal Processing Blocks
+ * \brief All C++ blocks that can be used from the OSMOSDR GNU Radio
* module are listed here or in the subcategories below.
*
*/
diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox
index 07b5bc2..55cd548 100644
--- a/docs/doxygen/other/main_page.dox
+++ b/docs/doxygen/other/main_page.dox
@@ -1,8 +1,8 @@
/*! \mainpage
-Welcome to the GNU Radio TEST Block
+Welcome to the GNU Radio OSMOSDR Block
-This is the intro page for the Doxygen manual generated for the TEST
+This is the intro page for the Doxygen manual generated for the OSMOSDR
block (docs/doxygen/other/main_page.dox). Edit it to add more detailed
documentation about the new GNU Radio modules contained in this
project.
diff --git a/gnuradio-osmosdr.pc.in b/gnuradio-osmosdr.pc.in
new file mode 100644
index 0000000..5f1ae69
--- /dev/null
+++ b/gnuradio-osmosdr.pc.in
@@ -0,0 +1,15 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/@GR_LIBRARY_DIR@
+includedir=${prefix}/@GR_INCLUDE_DIR@
+
+Name: @CPACK_PACKAGE_NAME@
+Description: @CPACK_PACKAGE_DESCRIPTION_SUMMARY@
+URL: http://sdr.osmocom.org/trac/wiki/GrOsmoSDR
+Version: @CPACK_PACKAGE_VERSION@
+Requires: gnuradio-runtime gnuradio-blocks
+Requires.private: @GR_OSMOSDR_PC_REQUIRES@
+Conflicts:
+Cflags: -I${includedir} @GR_OSMOSDR_PC_CFLAGS@
+Libs: -L${libdir} -lgnuradio-osmosdr
+Libs.private: @GR_OSMOSDR_PC_LIBS@
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index 3bb52f8..714d88c 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -1,24 +1,24 @@
# Copyright 2011 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
########################################################################
-# Rules for generating the source and sink yml wrappers
+# Rules for generating the source and sink xml wrappers
########################################################################
include(GrPython)
diff --git a/grc/gen_osmosdr_blocks.py b/grc/gen_osmosdr_blocks.py
index 4cca82f..840320a 100644
--- a/grc/gen_osmosdr_blocks.py
+++ b/grc/gen_osmosdr_blocks.py
@@ -122,11 +122,11 @@ templates:
${'%'} if context.get('nchan')() > ${n}:
self.${'$'}{id}.set_center_freq(${'$'}{${'freq' + str(n)}}, ${n})
self.${'$'}{id}.set_freq_corr(${'$'}{${'corr' + str(n)}}, ${n})
- % if sourk == 'source':
+ ${'%'} if context.get('sourk') == 'source':
self.${'$'}{id}.set_dc_offset_mode(${'$'}{${'dc_offset_mode' + str(n)}}, ${n})
self.${'$'}{id}.set_iq_balance_mode(${'$'}{${'iq_balance_mode' + str(n)}}, ${n})
self.${'$'}{id}.set_gain_mode(${'$'}{${'gain_mode' + str(n)}}, ${n})
- % endif
+ ${'%'} endif
self.${'$'}{id}.set_gain(${'$'}{${'gain' + str(n)}}, ${n})
self.${'$'}{id}.set_if_gain(${'$'}{${'if_gain' + str(n)}}, ${n})
self.${'$'}{id}.set_bb_gain(${'$'}{${'bb_gain' + str(n)}}, ${n})
@@ -157,8 +157,10 @@ documentation: |-
While primarily being developed for the OsmoSDR hardware, this block as well supports:
% if sourk == 'source':
+ * sysmocom OsmoSDR Devices through libosmosdr
* RTL2832U based DVB-T dongles through librtlsdr
* RTL-TCP spectrum server (see librtlsdr project)
+ * MSi2500 based DVB-T dongles through libmirisdr
* SDRplay RSP devices through SDRplay library
* gnuradio .cfile input through libgnuradio-blocks
* RFSPACE SDR-IQ, SDR-IP, NetSDR (incl. X2 option)
@@ -171,8 +173,7 @@ documentation: |-
* Great Scott Gadgets HackRF through libhackrf
* Nuand LLC bladeRF through libbladeRF library
* Ettus USRP Devices through Ettus UHD library
- * Fairwaves XTRX through libxtrx
- * Fairwaves UmTRX through Fairwaves' module for UHD
+ * Fairwaves UmTRX through Fairwaves' fork of UHD
* Red Pitaya SDR transceiver (http://bazaar.redpitaya.com)
* FreeSRP through libfreesrp library
@@ -191,11 +192,13 @@ documentation: |-
Lines ending with ... mean it's possible to bind devices together by specifying multiple device arguments separated with a space.
% if sourk == 'source':
+ miri=0[,buffers=32] ...
rtl=serial_number ...
rtl=0[,rtl_xtal=28.8e6][,tuner_xtal=28.8e6] ...
rtl=1[,buffers=32][,buflen=N*512] ...
rtl=2[,direct_samp=0|1|2][,offset_tune=0|1][,bias=0|1] ...
rtl_tcp=127.0.0.1:1234[,psize=16384][,direct_samp=0|1|2][,offset_tune=0|1][,bias=0|1] ...
+ osmosdr=0[,buffers=32][,buflen=N*512] ...
file='/path/to/your file',rate=1e6[,freq=100e6][,repeat=true][,throttle=true] ...
netsdr=127.0.0.1[:50000][,nchan=2]
sdr-ip=127.0.0.1[:50000]
@@ -211,7 +214,6 @@ documentation: |-
hackrf=0[,buffers=32][,bias=0|1][,bias_tx=0|1]
bladerf=0[,tamer=internal|external|external_1pps][,smb=25e6]
uhd[,serial=...][,lo_offset=0][,mcr=52e6][,nchan=2][,subdev='\\\\'B:0 A:0\\\\''] ...
- xtrx
Num Channels:
Selects the total number of channels in this multi-device configuration. Required when specifying multiple device arguments.
diff --git a/include/osmosdr/CMakeLists.txt b/include/osmosdr/CMakeLists.txt
index 9d284d6..d185ee6 100644
--- a/include/osmosdr/CMakeLists.txt
+++ b/include/osmosdr/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2011 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
diff --git a/include/osmosdr/pimpl.h b/include/osmosdr/pimpl.h
index 3a99994..e1985b4 100644
--- a/include/osmosdr/pimpl.h
+++ b/include/osmosdr/pimpl.h
@@ -18,7 +18,7 @@
#ifndef INCLUDED_OSMOSDR_PIMPL_H
#define INCLUDED_OSMOSDR_PIMPL_H
-#include <memory>
+#include <boost/shared_ptr.hpp>
/*! \file pimpl.h
* "Pimpl idiom" (pointer to implementation idiom).
@@ -39,7 +39,7 @@
* \param _name the name of the pimpl class
*/
#define OSMOSDR_PIMPL_DECL(_name) \
- struct _name; std::shared_ptr<_name>
+ struct _name; boost::shared_ptr<_name>
/*!
* Make an instance of a pimpl in a source file.
@@ -49,6 +49,6 @@
* \param _args the constructor args for the pimpl
*/
#define OSMOSDR_PIMPL_MAKE(_name, _args) \
- std::shared_ptr<_name>(new _name _args)
+ boost::shared_ptr<_name>(new _name _args)
#endif /* INCLUDED_OSMOSDR_PIMPL_H */
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 1bb8655..d95109b 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -1,32 +1,41 @@
# Copyright 2011 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
########################################################################
# Setup library
########################################################################
-include(GrPlatform) #define LIB_SUFFIX
+INCLUDE(GrPlatform) #define LIB_SUFFIX
+INCLUDE(GrMiscUtils)
+INCLUDE(GrComponent)
########################################################################
-# Setup target
+# Helpful Macros
########################################################################
+MACRO(GR_OSMOSDR_APPEND_SRCS)
+ LIST(APPEND gr_osmosdr_srcs ${ARGV})
+ENDMACRO(GR_OSMOSDR_APPEND_SRCS)
-list(APPEND gr_osmosdr_srcs
+MACRO(GR_OSMOSDR_APPEND_LIBS)
+ LIST(APPEND gr_osmosdr_libs ${ARGV})
+ENDMACRO(GR_OSMOSDR_APPEND_LIBS)
+
+GR_OSMOSDR_APPEND_SRCS(
source_impl.cc
sink_impl.cc
ranges.cc
@@ -34,44 +43,28 @@ list(APPEND gr_osmosdr_srcs
time_spec.cc
)
+set(CMAKE_CXX_STANDARD 11)
+
#-pthread Adds support for multithreading with the pthreads library.
#This option sets flags for both the preprocessor and linker. (man gcc)
if(CMAKE_COMPILER_IS_GNUCXX)
list(APPEND Boost_LIBRARIES -pthread)
endif()
-#dirty macro to allow appending from subdirs
-#this appends all unnamed implicit macro args!
-MACRO (APPEND_LIB_LIST)
- SET (gr_osmosdr_libs "${gr_osmosdr_libs};${ARGN}" CACHE INTERNAL "lib list")
-ENDMACRO (APPEND_INTERNAL_LIST)
-
-set(gr_osmosdr_libs "" CACHE INTERNAL "lib that accumulates link targets")
-
-add_library(gnuradio-osmosdr SHARED)
-APPEND_LIB_LIST(${Boost_LIBRARIES} gnuradio::gnuradio-runtime)
-target_include_directories(gnuradio-osmosdr
- PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
- PUBLIC ${Boost_INCLUDE_DIRS}
- PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
- PUBLIC $<INSTALL_INTERFACE:include>
- )
-set_target_properties(gnuradio-osmosdr PROPERTIES DEFINE_SYMBOL "gnuradio_osmosdr_EXPORTS")
-
-if(APPLE)
- set_target_properties(gnuradio-osmosdr PROPERTIES
- INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib"
- )
-endif(APPLE)
+GR_OSMOSDR_APPEND_LIBS(
+ ${Boost_LIBRARIES}
+ gnuradio::gnuradio-blocks
+ ${GNURADIO_ALL_LIBRARIES}
+)
########################################################################
# Setup defines for high resolution timing
########################################################################
-message(STATUS "")
-message(STATUS "Configuring high resolution timing...")
-include(CheckCXXSourceCompiles)
+MESSAGE(STATUS "")
+MESSAGE(STATUS "Configuring high resolution timing...")
+INCLUDE(CheckCXXSourceCompiles)
-set(CMAKE_REQUIRED_LIBRARIES -lrt)
+SET(CMAKE_REQUIRED_LIBRARIES -lrt)
CHECK_CXX_SOURCE_COMPILES("
#include <ctime>
int main(){
@@ -80,9 +73,9 @@ CHECK_CXX_SOURCE_COMPILES("
}
" HAVE_CLOCK_GETTIME
)
-unset(CMAKE_REQUIRED_LIBRARIES)
+UNSET(CMAKE_REQUIRED_LIBRARIES)
-include(CheckCXXSourceCompiles)
+INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("
#include <mach/mach_time.h>
int main(){
@@ -105,22 +98,22 @@ CHECK_CXX_SOURCE_COMPILES("
" HAVE_QUERY_PERFORMANCE_COUNTER
)
-if(HAVE_CLOCK_GETTIME)
- message(STATUS " High resolution timing supported through clock_gettime.")
- set(TIME_SPEC_DEFS HAVE_CLOCK_GETTIME)
- APPEND_LIB_LIST( "-lrt")
-elseif(HAVE_MACH_ABSOLUTE_TIME)
- message(STATUS " High resolution timing supported through mach_absolute_time.")
- set(TIME_SPEC_DEFS HAVE_MACH_ABSOLUTE_TIME)
-elseif(HAVE_QUERY_PERFORMANCE_COUNTER)
- message(STATUS " High resolution timing supported through QueryPerformanceCounter.")
- set(TIME_SPEC_DEFS HAVE_QUERY_PERFORMANCE_COUNTER)
-else()
- message(STATUS " High resolution timing supported through microsec_clock.")
- set(TIME_SPEC_DEFS HAVE_MICROSEC_CLOCK)
-endif()
-
-set_source_files_properties(
+IF(HAVE_CLOCK_GETTIME)
+ MESSAGE(STATUS " High resolution timing supported through clock_gettime.")
+ SET(TIME_SPEC_DEFS HAVE_CLOCK_GETTIME)
+ GR_OSMOSDR_APPEND_LIBS("-lrt")
+ELSEIF(HAVE_MACH_ABSOLUTE_TIME)
+ MESSAGE(STATUS " High resolution timing supported through mach_absolute_time.")
+ SET(TIME_SPEC_DEFS HAVE_MACH_ABSOLUTE_TIME)
+ELSEIF(HAVE_QUERY_PERFORMANCE_COUNTER)
+ MESSAGE(STATUS " High resolution timing supported through QueryPerformanceCounter.")
+ SET(TIME_SPEC_DEFS HAVE_QUERY_PERFORMANCE_COUNTER)
+ELSE()
+ MESSAGE(STATUS " High resolution timing supported through microsec_clock.")
+ SET(TIME_SPEC_DEFS HAVE_MICROSEC_CLOCK)
+ENDIF()
+
+SET_SOURCE_FILES_PROPERTIES(
time_spec.cc
PROPERTIES COMPILE_DEFINITIONS "${TIME_SPEC_DEFS}"
)
@@ -128,27 +121,27 @@ set_source_files_properties(
########################################################################
# Setup IQBalance component
########################################################################
-GR_REGISTER_COMPONENT("Osmocom IQ Imbalance Correction" ENABLE_IQBALANCE gnuradio-iqbalance_FOUND)
+GR_REGISTER_COMPONENT("Osmocom IQ Imbalance Correction" ENABLE_IQBALANCE GNURADIO_IQBALANCE_FOUND)
if(ENABLE_IQBALANCE)
- add_definitions(-DHAVE_IQBALANCE=1)
- target_include_directories(gnuradio-osmosdr PRIVATE ${gnuradio-iqbalance_INCLUDE_DIRS})
- APPEND_LIB_LIST( gnuradio::gnuradio-iqbalance)
+add_definitions(-DHAVE_IQBALANCE=1)
+include_directories(${GNURADIO_IQBALANCE_INCLUDE_DIRS})
+GR_OSMOSDR_APPEND_LIBS(${GNURADIO_IQBALANCE_LIBRARIES})
endif(ENABLE_IQBALANCE)
########################################################################
-# Setup FCD component
+# Setup OsmoSDR component
########################################################################
-GR_REGISTER_COMPONENT("FUNcube Dongle" ENABLE_FCD GNURADIO_FCDPP_FOUND)
-if(ENABLE_FCD)
- add_subdirectory(fcd)
-endif(ENABLE_FCD)
+GR_REGISTER_COMPONENT("sysmocom OsmoSDR" ENABLE_OSMOSDR LIBOSMOSDR_FOUND)
+if(ENABLE_OSMOSDR)
+GR_INCLUDE_SUBDIRECTORY(osmosdr)
+endif(ENABLE_OSMOSDR)
########################################################################
# Setup File component
########################################################################
-GR_REGISTER_COMPONENT("IQ File Source & Sink" ENABLE_FILE gnuradio-blocks_FOUND)
+GR_REGISTER_COMPONENT("IQ File Source & Sink" ENABLE_FILE GNURADIO_BLOCKS_FOUND)
if(ENABLE_FILE)
- add_subdirectory(file)
+GR_INCLUDE_SUBDIRECTORY(file)
endif(ENABLE_FILE)
########################################################################
@@ -156,32 +149,40 @@ endif(ENABLE_FILE)
########################################################################
GR_REGISTER_COMPONENT("Osmocom RTLSDR" ENABLE_RTL LIBRTLSDR_FOUND)
if(ENABLE_RTL)
- add_subdirectory(rtl)
+GR_INCLUDE_SUBDIRECTORY(rtl)
endif(ENABLE_RTL)
########################################################################
# Setup RTL_TCP component
########################################################################
-GR_REGISTER_COMPONENT("RTLSDR TCP Client" ENABLE_RTL_TCP gnuradio-blocks_FOUND)
+GR_REGISTER_COMPONENT("RTLSDR TCP Client" ENABLE_RTL_TCP GNURADIO_BLOCKS_FOUND)
if(ENABLE_RTL_TCP)
- add_subdirectory(rtl_tcp)
+GR_INCLUDE_SUBDIRECTORY(rtl_tcp)
endif(ENABLE_RTL_TCP)
########################################################################
# Setup UHD component
########################################################################
-GR_REGISTER_COMPONENT("Ettus USRP Devices" ENABLE_UHD UHD_FOUND gnuradio-uhd_FOUND)
+GR_REGISTER_COMPONENT("Ettus USRP Devices" ENABLE_UHD UHD_FOUND GNURADIO_UHD_FOUND)
if(ENABLE_UHD)
- add_subdirectory(uhd)
+GR_INCLUDE_SUBDIRECTORY(uhd)
endif(ENABLE_UHD)
########################################################################
+# Setup MiriSDR component
+########################################################################
+GR_REGISTER_COMPONENT("Osmocom MiriSDR" ENABLE_MIRI LIBMIRISDR_FOUND)
+if(ENABLE_MIRI)
+GR_INCLUDE_SUBDIRECTORY(miri)
+endif(ENABLE_MIRI)
+
+########################################################################
# Setup SDRplay component
########################################################################
if(ENABLE_NONFREE)
GR_REGISTER_COMPONENT("SDRplay RSP (NONFREE)" ENABLE_SDRPLAY LIBSDRPLAY_FOUND)
if(ENABLE_SDRPLAY)
- add_subdirectory(sdrplay)
+GR_INCLUDE_SUBDIRECTORY(sdrplay)
endif(ENABLE_SDRPLAY)
endif(ENABLE_NONFREE)
@@ -190,7 +191,7 @@ endif(ENABLE_NONFREE)
########################################################################
GR_REGISTER_COMPONENT("HackRF & rad1o Badge" ENABLE_HACKRF LIBHACKRF_FOUND)
if(ENABLE_HACKRF)
- add_subdirectory(hackrf)
+GR_INCLUDE_SUBDIRECTORY(hackrf)
endif(ENABLE_HACKRF)
########################################################################
@@ -198,7 +199,7 @@ endif(ENABLE_HACKRF)
########################################################################
GR_REGISTER_COMPONENT("nuand bladeRF" ENABLE_BLADERF LIBBLADERF_FOUND)
if(ENABLE_BLADERF)
- add_subdirectory(bladerf)
+GR_INCLUDE_SUBDIRECTORY(bladerf)
endif(ENABLE_BLADERF)
########################################################################
@@ -206,7 +207,7 @@ endif(ENABLE_BLADERF)
########################################################################
GR_REGISTER_COMPONENT("RFSPACE Receivers" ENABLE_RFSPACE)
if(ENABLE_RFSPACE)
- add_subdirectory(rfspace)
+GR_INCLUDE_SUBDIRECTORY(rfspace)
endif(ENABLE_RFSPACE)
########################################################################
@@ -214,23 +215,15 @@ endif(ENABLE_RFSPACE)
########################################################################
GR_REGISTER_COMPONENT("AIRSPY Receiver" ENABLE_AIRSPY LIBAIRSPY_FOUND)
if(ENABLE_AIRSPY)
- add_subdirectory(airspy)
+GR_INCLUDE_SUBDIRECTORY(airspy)
endif(ENABLE_AIRSPY)
########################################################################
-# Setup AIRSPYHF component
-########################################################################
-GR_REGISTER_COMPONENT("AIRSPY HF+ Receiver" ENABLE_AIRSPYHF LIBAIRSPYHF_FOUND)
-if(ENABLE_AIRSPYHF)
- add_subdirectory(airspyhf)
-endif(ENABLE_AIRSPYHF)
-
-########################################################################
# Setup SoapySDR component
########################################################################
GR_REGISTER_COMPONENT("SoapySDR support" ENABLE_SOAPY SoapySDR_FOUND)
if(ENABLE_SOAPY)
- add_subdirectory(soapy)
+GR_INCLUDE_SUBDIRECTORY(soapy)
endif(ENABLE_SOAPY)
########################################################################
@@ -238,7 +231,7 @@ endif(ENABLE_SOAPY)
########################################################################
GR_REGISTER_COMPONENT("Red Pitaya SDR" ENABLE_REDPITAYA)
if(ENABLE_REDPITAYA)
- add_subdirectory(redpitaya)
+GR_INCLUDE_SUBDIRECTORY(redpitaya)
endif(ENABLE_REDPITAYA)
########################################################################
@@ -246,35 +239,37 @@ endif(ENABLE_REDPITAYA)
########################################################################
GR_REGISTER_COMPONENT("FreeSRP support" ENABLE_FREESRP LIBFREESRP_FOUND)
if(ENABLE_FREESRP)
- add_subdirectory(freesrp)
+GR_INCLUDE_SUBDIRECTORY(freesrp)
endif(ENABLE_FREESRP)
########################################################################
-# Setup XTRX component
-########################################################################
-GR_REGISTER_COMPONENT("XTRX SDR" ENABLE_XTRX LIBXTRX_FOUND)
-if(ENABLE_XTRX)
- add_subdirectory(xtrx)
-endif(ENABLE_XTRX)
-
-########################################################################
# Setup configuration file
########################################################################
-add_definitions(-DHAVE_CONFIG_H=1)
+ADD_DEFINITIONS(-DHAVE_CONFIG_H=1)
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
-configure_file(
+CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h
@ONLY)
########################################################################
-# Finalize target
+# Set up Windows DLL resource files
########################################################################
-set_target_properties(gnuradio-osmosdr PROPERTIES SOURCES "${gr_osmosdr_srcs}")
-target_link_libraries(gnuradio-osmosdr ${gr_osmosdr_libs})
+IF(MSVC)
+ include(${CMAKE_SOURCE_DIR}/cmake/Modules/GrVersion.cmake)
+
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-osmosdr.rc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-osmosdr.rc
+ @ONLY)
+
+ GR_OSMOSDR_APPEND_SRCS(${CMAKE_CURRENT_BINARY_DIR}/gnuradio-osmosdr.rc)
+ENDIF(MSVC)
########################################################################
-# Install built library files
+# Setup libgnuradio-osmosdr library
########################################################################
-include(GrMiscUtils)
+ADD_LIBRARY(gnuradio-osmosdr SHARED ${gr_osmosdr_srcs})
+TARGET_LINK_LIBRARIES(gnuradio-osmosdr ${gr_osmosdr_libs})
+SET_TARGET_PROPERTIES(gnuradio-osmosdr PROPERTIES DEFINE_SYMBOL "gnuradio_osmosdr_EXPORTS")
GR_LIBRARY_FOO(gnuradio-osmosdr)
diff --git a/lib/airspy/CMakeLists.txt b/lib/airspy/CMakeLists.txt
index 187d938..3e34aa6 100644
--- a/lib/airspy/CMakeLists.txt
+++ b/lib/airspy/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,18 +21,17 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${LIBAIRSPY_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- gnuradio::gnuradio-filter
- ${Gnuradio-blocks_LIBRARIES}
- ${LIBAIRSPY_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(airspy_srcs
${CMAKE_CURRENT_SOURCE_DIR}/airspy_source_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${airspy_srcs})
+list(APPEND gr_osmosdr_libs ${LIBAIRSPY_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES})
diff --git a/lib/airspy/airspy_source_c.cc b/lib/airspy/airspy_source_c.cc
index 7fd3be8..50150e5 100644
--- a/lib/airspy/airspy_source_c.cc
+++ b/lib/airspy/airspy_source_c.cc
@@ -33,6 +33,7 @@
#include <boost/assign.hpp>
#include <boost/format.hpp>
+#include <boost/detail/endian.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/thread/thread.hpp>
@@ -290,7 +291,7 @@ int airspy_source_c::work( int noutput_items,
if ( ! running )
return WORK_DONE;
- std::unique_lock<std::mutex> lock(_fifo_lock);
+ boost::unique_lock<boost::mutex> lock(_fifo_lock);
/* Wait until we have the requested number of samples */
int n_samples_avail = _fifo->size();
diff --git a/lib/airspy/airspy_source_c.h b/lib/airspy/airspy_source_c.h
index a7d817f..f8617e6 100644
--- a/lib/airspy/airspy_source_c.h
+++ b/lib/airspy/airspy_source_c.h
@@ -23,9 +23,8 @@
#define INCLUDED_AIRSPY_SOURCE_C_H
#include <boost/circular_buffer.hpp>
-
-#include <mutex>
-#include <condition_variable>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <gnuradio/sync_block.h>
@@ -129,8 +128,8 @@ private:
airspy_device *_dev;
boost::circular_buffer<gr_complex> *_fifo;
- std::mutex _fifo_lock;
- std::condition_variable _samp_avail;
+ boost::mutex _fifo_lock;
+ boost::condition_variable _samp_avail;
std::vector< std::pair<double, uint32_t> > _sample_rates;
double _sample_rate;
diff --git a/lib/airspyhf/airspyhf_source_c.cc b/lib/airspyhf/airspyhf_source_c.cc
deleted file mode 100644
index 26e0134..0000000
--- a/lib/airspyhf/airspyhf_source_c.cc
+++ /dev/null
@@ -1,437 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-/*
- * config.h is generated by configure. It contains the results
- * of probing for features, options etc. It should be the first
- * file included in your .cc file.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdexcept>
-#include <iostream>
-#include <algorithm>
-
-#include <boost/assign.hpp>
-#include <boost/format.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/thread/thread.hpp>
-
-#include <gnuradio/io_signature.h>
-
-#include "airspyhf_source_c.h"
-#include "arg_helpers.h"
-
-using namespace boost::assign;
-
-#define AIRSPYHF_FORMAT_ERROR(ret, msg) \
- boost::str( boost::format(msg " (%1%)") % ret )
-
-#define AIRSPYHF_THROW_ON_ERROR(ret, msg) \
- if ( ret != AIRSPYHF_SUCCESS ) \
- { \
- throw std::runtime_error( AIRSPYHF_FORMAT_ERROR(ret, msg) ); \
- }
-
-#define AIRSPYHF_FUNC_STR(func, arg) \
- boost::str(boost::format(func "(%1%)") % arg) + " has failed"
-
-airspyhf_source_c_sptr make_airspyhf_source_c (const std::string & args)
-{
- return gnuradio::get_initial_sptr(new airspyhf_source_c (args));
-}
-
-/*
- * Specify constraints on number of input and output streams.
- * This info is used to construct the input and output signatures
- * (2nd & 3rd args to gr::block's constructor). The input and
- * output signatures are used by the runtime system to
- * check that a valid number and type of inputs and outputs
- * are connected to this block. In this case, we accept
- * only 0 input and 1 output.
- */
-static const int MIN_IN = 0; // mininum number of input streams
-static const int MAX_IN = 0; // maximum number of input streams
-static const int MIN_OUT = 1; // minimum number of output streams
-static const int MAX_OUT = 1; // maximum number of output streams
-
-/*
- * The private constructor
- */
-airspyhf_source_c::airspyhf_source_c (const std::string &args)
- : gr::sync_block ("airspyhf_source_c",
- gr::io_signature::make(MIN_IN, MAX_IN, sizeof (gr_complex)),
- gr::io_signature::make(MIN_OUT, MAX_OUT, sizeof (gr_complex))),
- _dev(NULL),
- _sample_rate(0),
- _center_freq(0),
- _freq_corr(0)
-{
- int ret;
-
- dict_t dict = params_to_dict(args);
-
- _dev = NULL;
- ret = airspyhf_open( &_dev );
- AIRSPYHF_THROW_ON_ERROR(ret, "Failed to open Airspy HF+ device")
-
- uint32_t num_rates;
- airspyhf_get_samplerates(_dev, &num_rates, 0);
- uint32_t *samplerates = (uint32_t *) malloc(num_rates * sizeof(uint32_t));
- airspyhf_get_samplerates(_dev, samplerates, num_rates);
- for (size_t i = 0; i < num_rates; i++)
- _sample_rates.push_back( std::pair<double, uint32_t>( samplerates[i], i ) );
- free(samplerates);
-
- /* since they may (and will) give us an unsorted array we have to sort it here
- * to play nice with the monotonic requirement of meta-range later on */
- std::sort(_sample_rates.begin(), _sample_rates.end());
-
- std::cerr << "Using libairspyhf" << AIRSPYHF_VERSION << ", samplerates: ";
-
- for (size_t i = 0; i < _sample_rates.size(); i++)
- std::cerr << boost::format("%gM ") % (_sample_rates[i].first / 1e6);
-
- std::cerr << std::endl;
-
- set_center_freq( (get_freq_range().start() + get_freq_range().stop()) / 2.0 );
- set_sample_rate( get_sample_rates().start() );
-
- _fifo = new boost::circular_buffer<gr_complex>(5000000);
- if (!_fifo) {
- throw std::runtime_error( std::string(__FUNCTION__) + " " +
- "Failed to allocate a sample FIFO!" );
- }
-}
-
-/*
- * Our virtual destructor.
- */
-airspyhf_source_c::~airspyhf_source_c ()
-{
- int ret;
-
- if (_dev) {
- if ( airspyhf_is_streaming( _dev ) )
- {
- ret = airspyhf_stop( _dev );
- if ( ret != AIRSPYHF_SUCCESS )
- {
- std::cerr << AIRSPYHF_FORMAT_ERROR(ret, "Failed to stop RX streaming") << std::endl;
- }
- }
-
- ret = airspyhf_close( _dev );
- if ( ret != AIRSPYHF_SUCCESS )
- {
- std::cerr << AIRSPYHF_FORMAT_ERROR(ret, "Failed to close AirSpy") << std::endl;
- }
- _dev = NULL;
- }
-
- if (_fifo)
- {
- delete _fifo;
- _fifo = NULL;
- }
-}
-
-int airspyhf_source_c::_airspyhf_rx_callback(airspyhf_transfer_t *transfer)
-{
- airspyhf_source_c *obj = (airspyhf_source_c *)transfer->ctx;
-
- return obj->airspyhf_rx_callback((float *)transfer->samples, transfer->sample_count);
-}
-
-int airspyhf_source_c::airspyhf_rx_callback(void *samples, int sample_count)
-{
- size_t i, n_avail, to_copy, num_samples = sample_count;
- float *sample = (float *)samples;
-
- _fifo_lock.lock();
-
- n_avail = _fifo->capacity() - _fifo->size();
- to_copy = (n_avail < num_samples ? n_avail : num_samples);
-
- for (i = 0; i < to_copy; i++ )
- {
- /* Push sample to the fifo */
- _fifo->push_back( gr_complex( *sample, *(sample+1) ) );
-
- /* offset to the next I+Q sample */
- sample += 2;
- }
-
- _fifo_lock.unlock();
-
- /* We have made some new samples available to the consumer in work() */
- if (to_copy) {
- //std::cerr << "+" << std::flush;
- _samp_avail.notify_one();
- }
-
- /* Indicate overrun, if neccesary */
- if (to_copy < num_samples)
- std::cerr << "O" << std::flush;
-
- return 0; // TODO: return -1 on error/stop
-}
-
-bool airspyhf_source_c::start()
-{
- if ( ! _dev )
- return false;
-
- int ret = airspyhf_start( _dev, _airspyhf_rx_callback, (void *)this );
- if ( ret != AIRSPYHF_SUCCESS ) {
- std::cerr << "Failed to start RX streaming (" << ret << ")" << std::endl;
- return false;
- }
-
- return true;
-}
-
-bool airspyhf_source_c::stop()
-{
- if ( ! _dev )
- return false;
-
- int ret = airspyhf_stop( _dev );
- if ( ret != AIRSPYHF_SUCCESS ) {
- std::cerr << "Failed to stop RX streaming (" << ret << ")" << std::endl;
- return false;
- }
-
- return true;
-}
-
-int airspyhf_source_c::work( int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items )
-{
- gr_complex *out = (gr_complex *)output_items[0];
-
- bool running = false;
-
- if ( _dev )
- running = airspyhf_is_streaming( _dev );
-
- if ( ! running )
- return WORK_DONE;
-
- std::unique_lock<std::mutex> lock(_fifo_lock);
-
- /* Wait until we have the requested number of samples */
- int n_samples_avail = _fifo->size();
-
- while (n_samples_avail < noutput_items) {
- _samp_avail.wait(lock);
- n_samples_avail = _fifo->size();
- }
-
- for(int i = 0; i < noutput_items; ++i) {
- out[i] = _fifo->at(0);
- _fifo->pop_front();
- }
-
- return noutput_items;
-}
-
-std::vector<std::string> airspyhf_source_c::get_devices()
-{
- std::vector<std::string> devices;
- std::string label;
-
- int ret;
- airspyhf_device *dev = NULL;
- ret = airspyhf_open(&dev);
- if ( AIRSPYHF_SUCCESS == ret )
- {
- std::string args = "airspyhf=0,label='AirspyHF'";
- devices.push_back( args );
- ret = airspyhf_close(dev);
- }
-
- return devices;
-}
-
-size_t airspyhf_source_c::get_num_channels()
-{
- return 1;
-}
-
-osmosdr::meta_range_t airspyhf_source_c::get_sample_rates()
-{
- osmosdr::meta_range_t range;
-
- for (size_t i = 0; i < _sample_rates.size(); i++)
- range += osmosdr::range_t( _sample_rates[i].first );
-
- return range;
-}
-
-double airspyhf_source_c::set_sample_rate( double rate )
-{
- int ret = AIRSPYHF_SUCCESS;
-
- if (_dev) {
- bool found_supported_rate = false;
- uint32_t samp_rate_index = 0;
-
- for( unsigned int i = 0; i < _sample_rates.size(); i++ )
- {
- if( _sample_rates[i].first == rate )
- {
- samp_rate_index = _sample_rates[i].second;
-
- found_supported_rate = true;
- }
- }
-
- if ( ! found_supported_rate )
- {
- throw std::runtime_error(
- boost::str( boost::format("Unsupported samplerate: %gM") % (rate/1e6) ) );
- }
-
- ret = airspyhf_set_samplerate( _dev, samp_rate_index );
- if ( AIRSPYHF_SUCCESS == ret ) {
- _sample_rate = rate;
- } else {
- AIRSPYHF_THROW_ON_ERROR( ret, AIRSPYHF_FUNC_STR( "airspyhf_set_samplerate", rate ) )
- }
- }
-
- return get_sample_rate();
-}
-
-double airspyhf_source_c::get_sample_rate()
-{
- return _sample_rate;
-}
-
-osmosdr::freq_range_t airspyhf_source_c::get_freq_range( size_t chan )
-{
- osmosdr::freq_range_t range;
-
- range += osmosdr::range_t( 0.0, 260.0e6 );
-
- return range;
-}
-
-double airspyhf_source_c::set_center_freq( double freq, size_t chan )
-{
- int ret;
-
- if (_dev) {
- ret = airspyhf_set_freq( _dev, freq );
- if ( AIRSPYHF_SUCCESS == ret ) {
- _center_freq = freq;
- } else {
- AIRSPYHF_THROW_ON_ERROR( ret, AIRSPYHF_FUNC_STR( "airspyhf_set_freq", freq ) )
- }
- }
-
- return get_center_freq( chan );
-}
-
-double airspyhf_source_c::get_center_freq( size_t chan )
-{
- return _center_freq;
-}
-
-double airspyhf_source_c::set_freq_corr( double ppm, size_t chan )
-{
- int ret;
- int32_t ppb = (int32_t) (ppm * 1.0e3);
-
- if (_dev) {
- ret = airspyhf_set_calibration( _dev, ppb );
- if ( AIRSPYHF_SUCCESS == ret ) {
- _freq_corr = ppm;
- } else {
- AIRSPYHF_THROW_ON_ERROR( ret, AIRSPYHF_FUNC_STR( "airspyhf_set_calibration", ppm ) )
- }
- }
-
- return ppm;
-}
-
-double airspyhf_source_c::get_freq_corr( size_t chan )
-{
- return _freq_corr;
-}
-
-std::vector<std::string> airspyhf_source_c::get_gain_names( size_t chan )
-{
- return {};
-}
-
-osmosdr::gain_range_t airspyhf_source_c::get_gain_range( size_t chan )
-{
- return osmosdr::gain_range_t();
-}
-
-osmosdr::gain_range_t airspyhf_source_c::get_gain_range( const std::string & name, size_t chan )
-{
- return osmosdr::gain_range_t();
-}
-
-
-double airspyhf_source_c::set_gain( double gain, size_t chan )
-{
- return gain;
-}
-
-double airspyhf_source_c::set_gain( double gain, const std::string & name, size_t chan)
-{
- return gain;
-}
-
-double airspyhf_source_c::get_gain( size_t chan )
-{
- return 0.0;
-}
-
-double airspyhf_source_c::get_gain( const std::string & name, size_t chan )
-{
- return 0.0;
-}
-
-std::vector< std::string > airspyhf_source_c::get_antennas( size_t chan )
-{
- std::vector< std::string > antennas;
-
- antennas += get_antenna( chan );
-
- return antennas;
-}
-
-std::string airspyhf_source_c::set_antenna( const std::string & antenna, size_t chan )
-{
- return get_antenna( chan );
-}
-
-std::string airspyhf_source_c::get_antenna( size_t chan )
-{
- return "RX";
-}
diff --git a/lib/arg_helpers.h b/lib/arg_helpers.h
index 3b02b8f..2278fa9 100644
--- a/lib/arg_helpers.h
+++ b/lib/arg_helpers.h
@@ -29,6 +29,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
#include <ciso646>
typedef std::map< std::string, std::string > dict_t;
@@ -37,7 +38,7 @@ typedef std::pair< std::string, std::string > pair_t;
inline std::string dict_to_args_string( const dict_t &d )
{
std::string out;
- for (const pair_t pair : d)
+ BOOST_FOREACH(const pair_t pair, d)
{
if (not out.empty()) out += ",";
out += pair.first + "='" + pair.second + "'";
@@ -53,7 +54,7 @@ inline std::vector< std::string > args_to_vector( const std::string &args )
typedef boost::tokenizer< boost::escaped_list_separator<char> > tokenizer_t;
tokenizer_t tokens(args, separator);
- for (std::string token : tokens)
+ BOOST_FOREACH(std::string token, tokens)
result.push_back(token);
return result;
@@ -67,7 +68,7 @@ inline std::vector< std::string > params_to_vector( const std::string &params )
typedef boost::tokenizer< boost::escaped_list_separator<char> > tokenizer_t;
tokenizer_t tokens(params, separator);
- for (std::string token : tokens)
+ BOOST_FOREACH(std::string token, tokens)
result.push_back(token);
return result;
@@ -97,7 +98,7 @@ inline dict_t params_to_dict( const std::string &params )
dict_t result;
std::vector< std::string > param_list = params_to_vector( params );
- for (std::string param : param_list)
+ BOOST_FOREACH(std::string param, param_list)
{
pair_t pair = param_to_pair( param );
std::string value = pair.second;
@@ -123,7 +124,7 @@ inline gr::io_signature::sptr args_to_io_signature( const std::string &args )
size_t dev_nchan = 0;
std::vector< std::string > arg_list = args_to_vector( args );
- for (std::string arg : arg_list)
+ BOOST_FOREACH( std::string arg, arg_list )
{
if ( arg.find( "numchan=" ) == 0 ) // try to parse global nchan value
{
@@ -140,7 +141,7 @@ inline gr::io_signature::sptr args_to_io_signature( const std::string &args )
// try to parse device specific nchan values, assume 1 channel if none given
- for (std::string arg : arg_list)
+ BOOST_FOREACH( std::string arg, arg_list )
{
dict_t dict = params_to_dict(arg);
if (dict.count("nchan"))
@@ -153,6 +154,8 @@ inline gr::io_signature::sptr args_to_io_signature( const std::string &args )
}
}
+ if (arg_list.size() <= 2 && max_nchan > dev_nchan)
+ dev_nchan = max_nchan;
// if at least one nchan was given, perform a sanity check
if ( max_nchan && dev_nchan && max_nchan != dev_nchan )
throw std::runtime_error("Wrong device arguments specified. Missing nchan?");
diff --git a/lib/bladerf/CMakeLists.txt b/lib/bladerf/CMakeLists.txt
index ea9cf49..c253a22 100644
--- a/lib/bladerf/CMakeLists.txt
+++ b/lib/bladerf/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2013 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,20 +21,20 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${LIBBLADERF_INCLUDE_DIRS}
- ${Volk_INCLUDE_DIRS}
+ ${VOLK_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- ${LIBBLADERF_LIBRARIES}
- ${Volk_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(bladerf_srcs
${CMAKE_CURRENT_SOURCE_DIR}/bladerf_source_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/bladerf_sink_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/bladerf_common.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${bladerf_srcs})
+list(APPEND gr_osmosdr_libs ${LIBBLADERF_LIBRARIES} ${VOLK_LIBRARIES})
diff --git a/lib/bladerf/bladerf_common.cc b/lib/bladerf/bladerf_common.cc
index 67bf736..93b039d 100644
--- a/lib/bladerf/bladerf_common.cc
+++ b/lib/bladerf/bladerf_common.cc
@@ -35,8 +35,10 @@
#include <string>
#include <boost/assign.hpp>
+#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/weak_ptr.hpp>
#include "bladerf_common.h"
@@ -48,8 +50,8 @@ static size_t const STREAM_TIMEOUT_MS = 3000;
using namespace boost::assign;
-std::mutex bladerf_common::_devs_mutex;
-std::list<std::weak_ptr<struct bladerf>> bladerf_common::_devs;
+boost::mutex bladerf_common::_devs_mutex;
+std::list<boost::weak_ptr<struct bladerf> > bladerf_common::_devs;
/* name for system-wide gain (which is not its own libbladeRF gain stage) */
static const char *SYSTEM_GAIN_NAME = "system";
@@ -133,7 +135,7 @@ size_t num_streams(bladerf_channel_layout layout)
* Public methods
******************************************************************************/
bladerf_common::bladerf_common() :
- _dev(NULL),
+ _dev(boost::shared_ptr<struct bladerf>()),
_pfx("[bladeRF common] "),
_failures(0),
_num_buffers(NUM_BUFFERS),
@@ -497,7 +499,7 @@ int bladerf_common::channel2rfport(bladerf_channel ch)
bladerf_channel bladerf_common::chan2channel(bladerf_direction direction,
size_t chan)
{
- for (bladerf_channel_map::value_type &i : _chanmap) {
+ BOOST_FOREACH(bladerf_channel_map::value_type &i, _chanmap) {
bladerf_channel ch = i.first;
if (
(i.second == (int)chan) && (
@@ -641,7 +643,7 @@ osmosdr::freq_range_t bladerf_common::filter_bandwidths(bladerf_channel ch)
0.75, 0.875, 1.25, 1.375, 1.5, 1.92, 2.5,
2.75, 3, 3.5, 4.375, 5, 6, 7, 10, 14;
- for (double half_bw : half_bandwidths)
+ BOOST_FOREACH( double half_bw, half_bandwidths )
bandwidths += osmosdr::range_t( half_bw * 2e6 );
#else
@@ -1077,7 +1079,7 @@ bladerf_sptr bladerf_common::open(std::string const &device_name)
struct bladerf *raw_dev = NULL;
struct bladerf_devinfo devinfo;
- std::lock_guard<std::mutex> lock(_devs_mutex);
+ boost::unique_lock<boost::mutex> lock(_devs_mutex);
/* Initialize the information used to identify the desired device
* to all wildcard (i.e., "any device") values */
@@ -1107,15 +1109,15 @@ bladerf_sptr bladerf_common::open(std::string const &device_name)
/* Add the device handle to our cache */
bladerf_sptr dev = bladerf_sptr(raw_dev, bladerf_common::close);
- _devs.push_back(static_cast<std::weak_ptr<struct bladerf>>(dev));
+ _devs.push_back(static_cast<boost::weak_ptr<struct bladerf> >(dev));
return dev;
}
void bladerf_common::close(void *dev)
{
- std::lock_guard<std::mutex> lock(_devs_mutex);
- std::list<std::weak_ptr<struct bladerf>>::iterator it(_devs.begin());
+ boost::unique_lock<boost::mutex> lock(_devs_mutex);
+ std::list<boost::weak_ptr<struct bladerf> >::iterator it(_devs.begin());
/* Prune expired entries from device cache */
while (it != _devs.end()) {
@@ -1135,7 +1137,7 @@ bladerf_sptr bladerf_common::get_cached_device(struct bladerf_devinfo devinfo)
int status;
struct bladerf_devinfo other_devinfo;
- for (std::weak_ptr<struct bladerf> dev : _devs) {
+ BOOST_FOREACH(boost::weak_ptr<struct bladerf> dev, _devs) {
status = bladerf_get_devinfo(bladerf_sptr(dev).get(), &other_devinfo);
if (status < 0) {
BLADERF_THROW_STATUS(status, "Failed to get devinfo for cached device");
@@ -1198,7 +1200,7 @@ void bladerf_common::print_device_info()
bool bladerf_common::is_antenna_valid(bladerf_direction dir,
const std::string &antenna)
{
- for (std::string ant : get_antennas(dir)) {
+ BOOST_FOREACH(std::string ant, get_antennas(dir)) {
if (antenna == ant) {
return true;
}
diff --git a/lib/bladerf/bladerf_common.h b/lib/bladerf/bladerf_common.h
index 741b1e7..51dedc9 100644
--- a/lib/bladerf/bladerf_common.h
+++ b/lib/bladerf/bladerf_common.h
@@ -23,11 +23,12 @@
#include <list>
#include <map>
-#include <memory>
-#include <mutex>
#include <string>
#include <vector>
+#include <boost/thread/mutex.hpp>
+#include <boost/weak_ptr.hpp>
+
#include <libbladeRF.h>
#include "osmosdr/ranges.h"
@@ -42,7 +43,7 @@ typedef ptrdiff_t ssize_t;
#define BLADERF_DEBUG_ENABLE
-typedef std::shared_ptr<struct bladerf> bladerf_sptr;
+typedef boost::shared_ptr<struct bladerf> bladerf_sptr;
/* Identification of the bladeRF hardware in use */
typedef enum {
@@ -286,8 +287,8 @@ private:
/*****************************************************************************
* Private members
****************************************************************************/
- static std::mutex _devs_mutex; /**< mutex for access to _devs */
- static std::list<std::weak_ptr<struct bladerf>> _devs; /**< dev cache */
+ static boost::mutex _devs_mutex; /**< mutex for access to _devs */
+ static std::list<boost::weak_ptr<struct bladerf> > _devs; /**< dev cache */
};
#endif
diff --git a/lib/bladerf/bladerf_compat.h b/lib/bladerf/bladerf_compat.h
index 2ad24be..45e6a16 100644
--- a/lib/bladerf/bladerf_compat.h
+++ b/lib/bladerf/bladerf_compat.h
@@ -66,7 +66,7 @@
}
/* Changed enums/defines */
- #define BLADERF_GAIN_DEFAULT BLADERF_GAIN_AUTOMATIC
+ #define BLADERF_GAIN_DEFAULT BLADERF_GAIN_MANUAL
#define BLADERF_GAIN_MGC BLADERF_GAIN_MANUAL
#define BLADERF_RX_MUX_BASEBAND BLADERF_RX_MUX_BASEBAND_LMS
diff --git a/lib/bladerf/bladerf_sink_c.cc b/lib/bladerf/bladerf_sink_c.cc
index 6ee3acd..d3d607b 100644
--- a/lib/bladerf/bladerf_sink_c.cc
+++ b/lib/bladerf/bladerf_sink_c.cc
@@ -96,7 +96,7 @@ bladerf_sink_c::bladerf_sink_c(const std::string &args) :
}
/* Initialize channel <-> antenna map */
- for (std::string ant : get_antennas()) {
+ BOOST_FOREACH(std::string ant, get_antennas()) {
_chanmap[str2channel(ant)] = -1;
}
@@ -174,11 +174,9 @@ bool bladerf_sink_c::start()
for (size_t ch = 0; ch < get_max_channels(); ++ch) {
bladerf_channel brfch = BLADERF_CHANNEL_TX(ch);
- if (get_channel_enable(brfch)) {
- status = bladerf_enable_module(_dev.get(), brfch, true);
- if (status != 0) {
- BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
- }
+ status = bladerf_enable_module(_dev.get(), brfch, get_channel_enable(brfch));
+ if (status != 0) {
+ BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
}
}
@@ -210,11 +208,9 @@ bool bladerf_sink_c::stop()
for (size_t ch = 0; ch < get_max_channels(); ++ch) {
bladerf_channel brfch = BLADERF_CHANNEL_TX(ch);
- if (get_channel_enable(brfch)) {
- status = bladerf_enable_module(_dev.get(), brfch, false);
- if (status != 0) {
- BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
- }
+ status = bladerf_enable_module(_dev.get(), brfch, get_channel_enable(brfch));
+ if (status != 0) {
+ BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
}
}
@@ -241,6 +237,11 @@ int bladerf_sink_c::work(int noutput_items,
return 0;
}
+ noutput_items &= ~(3ULL);
+ if (!noutput_items) {
+ return 0;
+ }
+
// copy the samples from input_items
gr_complex const **in = reinterpret_cast<gr_complex const **>(&input_items[0]);
@@ -329,7 +330,7 @@ int bladerf_sink_c::transmit_with_tags(int16_t const *samples,
}
}
- for (gr::tag_t tag : tags) {
+ BOOST_FOREACH(gr::tag_t tag, tags) {
// Upon seeing an SOB tag, update our offset. We'll TX the start of the
// burst when we see an EOB or at the end of this function - whichever
// occurs first.
diff --git a/lib/bladerf/bladerf_source_c.cc b/lib/bladerf/bladerf_source_c.cc
index 83db677..e37bd67 100644
--- a/lib/bladerf/bladerf_source_c.cc
+++ b/lib/bladerf/bladerf_source_c.cc
@@ -144,7 +144,7 @@ bladerf_source_c::bladerf_source_c(const std::string &args) :
}
/* Initialize channel <-> antenna map */
- for (std::string ant : get_antennas()) {
+ BOOST_FOREACH(std::string ant, get_antennas()) {
_chanmap[str2channel(ant)] = -1;
}
@@ -180,7 +180,7 @@ bladerf_source_c::bladerf_source_c(const std::string &args) :
bool bladerf_source_c::is_antenna_valid(const std::string &antenna)
{
- for (std::string ant : get_antennas()) {
+ BOOST_FOREACH(std::string ant, get_antennas()) {
if (antenna == ant) {
return true;
}
@@ -230,11 +230,9 @@ bool bladerf_source_c::start()
for (size_t ch = 0; ch < get_max_channels(); ++ch) {
bladerf_channel brfch = BLADERF_CHANNEL_RX(ch);
- if (get_channel_enable(brfch)) {
- status = bladerf_enable_module(_dev.get(), brfch, true);
- if (status != 0) {
- BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
- }
+ status = bladerf_enable_module(_dev.get(), brfch, get_channel_enable(brfch));
+ if (status != 0) {
+ BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
}
}
@@ -344,7 +342,7 @@ int bladerf_source_c::work(int noutput_items,
memcpy(out[0], _32fcbuf, sizeof(gr_complex) * noutput_items);
}
- return noutput_items;
+ return noutput_items/(get_num_channels());
}
osmosdr::meta_range_t bladerf_source_c::get_sample_rates()
diff --git a/lib/config.h.in b/lib/config.h.in
index d96cd80..42e72f1 100644
--- a/lib/config.h.in
+++ b/lib/config.h.in
@@ -4,21 +4,21 @@
#define GR_OSMOSDR_VERSION "@VERSION@"
#define GR_OSMOSDR_LIBVER "@LIBVER@"
+#cmakedefine ENABLE_OSMOSDR
#cmakedefine ENABLE_FCD
#cmakedefine ENABLE_FILE
#cmakedefine ENABLE_RTL
#cmakedefine ENABLE_RTL_TCP
#cmakedefine ENABLE_UHD
+#cmakedefine ENABLE_MIRI
#cmakedefine ENABLE_SDRPLAY
#cmakedefine ENABLE_HACKRF
#cmakedefine ENABLE_BLADERF
#cmakedefine ENABLE_RFSPACE
#cmakedefine ENABLE_AIRSPY
-#cmakedefine ENABLE_AIRSPYHF
#cmakedefine ENABLE_SOAPY
#cmakedefine ENABLE_REDPITAYA
#cmakedefine ENABLE_FREESRP
-#cmakedefine ENABLE_XTRX
//provide NAN define for MSVC older than VC12
#if defined(_MSC_VER) && (_MSC_VER < 1800)
diff --git a/lib/device.cc b/lib/device.cc
index d072e27..025a22b 100644
--- a/lib/device.cc
+++ b/lib/device.cc
@@ -20,15 +20,20 @@
#include <osmosdr/device.h>
#include <stdexcept>
+#include <boost/foreach.hpp>
#include <boost/format.hpp>
+#include <boost/thread/mutex.hpp>
#include <algorithm>
-#include <mutex>
#include <sstream>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#ifdef ENABLE_OSMOSDR
+#include <osmosdr_src_c.h>
+#endif
+
#ifdef ENABLE_FCD
#include <fcd_source_c.h>
#endif
@@ -49,6 +54,10 @@
#include <uhd_source_c.h>
#endif
+#ifdef ENABLE_MIRI
+#include <miri_source_c.h>
+#endif
+
#ifdef ENABLE_SDRPLAY
#include <sdrplay_source_c.h>
#endif
@@ -69,10 +78,6 @@
#include <airspy_source_c.h>
#endif
-#ifdef ENABLE_AIRSPYHF
-#include <airspyhf_source_c.h>
-#endif
-
#ifdef ENABLE_SOAPY
#include <soapy_source_c.h>
#endif
@@ -93,13 +98,13 @@ static const std::string args_delim = " ";
static const std::string pairs_delim = ",";
static const std::string pair_delim = "=";
-static std::mutex _device_mutex;
+static boost::mutex _device_mutex;
device_t::device_t(const std::string &args)
{
dict_t dict = params_to_dict(args);
- for (dict_t::value_type &entry : dict)
+ BOOST_FOREACH( dict_t::value_type &entry, dict )
(*this)[entry.first] = entry.second;
}
@@ -109,7 +114,7 @@ std::string device_t::to_pp_string(void) const
std::stringstream ss;
ss << "Device Address:" << std::endl;
- for (const device_t::value_type &entry : *this) {
+ BOOST_FOREACH(const device_t::value_type &entry, *this) {
ss << boost::format(" %s: %s") % entry.first % entry.second << std::endl;
}
return ss.str();
@@ -119,7 +124,7 @@ std::string device_t::to_string(void) const
{
std::stringstream ss;
size_t count = 0;
- for (const device_t::value_type &entry : *this) {
+ BOOST_FOREACH(const device_t::value_type &entry, *this) {
std::string value = entry.second;
if (value.find(" ") != std::string::npos)
value = "'" + value + "'";
@@ -132,7 +137,7 @@ std::string device_t::to_string(void) const
devices_t device::find(const device_t &hint)
{
- std::lock_guard<std::mutex> lock(_device_mutex);
+ boost::mutex::scoped_lock lock(_device_mutex);
bool fake = true;
@@ -141,48 +146,52 @@ devices_t device::find(const device_t &hint)
devices_t devices;
+#ifdef ENABLE_OSMOSDR
+ BOOST_FOREACH( std::string dev, osmosdr_src_c::get_devices() )
+ devices.push_back( device_t(dev) );
+#endif
#ifdef ENABLE_FCD
- for (std::string dev : fcd_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, fcd_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_RTL
- for (std::string dev : rtl_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, rtl_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_UHD
- for (std::string dev : uhd_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, uhd_source_c::get_devices() )
+ devices.push_back( device_t(dev) );
+#endif
+#ifdef ENABLE_MIRI
+ BOOST_FOREACH( std::string dev, miri_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_SDRPLAY
- for (std::string dev : sdrplay_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, sdrplay_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_BLADERF
- for (std::string dev : bladerf_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, bladerf_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_HACKRF
- for (std::string dev : hackrf_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, hackrf_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_RFSPACE
- for (std::string dev : rfspace_source_c::get_devices( fake ))
+ BOOST_FOREACH( std::string dev, rfspace_source_c::get_devices( fake ) )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_AIRSPY
- for (std::string dev : airspy_source_c::get_devices())
- devices.push_back( device_t(dev) );
-#endif
-#ifdef ENABLE_AIRSPYHF
- for (std::string dev : airspyhf_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, airspy_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_FREESRP
- for (std::string dev : freesrp_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, freesrp_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_SOAPY
- for (std::string dev : soapy_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, soapy_source_c::get_devices() )
devices.push_back( device_t(dev) );
#endif
@@ -191,15 +200,15 @@ devices_t device::find(const device_t &hint)
* in a graphical interface etc... */
#ifdef ENABLE_RTL_TCP
- for (std::string dev : rtl_tcp_source_c::get_devices( fake ))
+ BOOST_FOREACH( std::string dev, rtl_tcp_source_c::get_devices( fake ) )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_REDPITAYA
- for (std::string dev : redpitaya_source_c::get_devices( fake ))
+ BOOST_FOREACH( std::string dev, redpitaya_source_c::get_devices( fake ) )
devices.push_back( device_t(dev) );
#endif
#ifdef ENABLE_FILE
- for (std::string dev : file_source_c::get_devices( fake ))
+ BOOST_FOREACH( std::string dev, file_source_c::get_devices( fake ) )
devices.push_back( device_t(dev) );
#endif
diff --git a/lib/fcd/CMakeLists.txt b/lib/fcd/CMakeLists.txt
index 768c5b2..e71b153 100644
--- a/lib/fcd/CMakeLists.txt
+++ b/lib/fcd/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,16 +21,29 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${GNURADIO_FCDPP_INCLUDE_DIRS}
-)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-APPEND_LIB_LIST(
- ${GNURADIO_FCDPP_LIBRARIES}
-)
+if(ENABLE_FCD)
+include_directories(${GNURADIO_FCD_INCLUDE_DIRS})
+endif(ENABLE_FCD)
-list(APPEND gr_osmosdr_srcs
+if(ENABLE_FCDPP)
+include_directories(${GNURADIO_FCDPP_INCLUDE_DIRS})
+endif(ENABLE_FCDPP)
+
+set(fcd_srcs
${CMAKE_CURRENT_SOURCE_DIR}/fcd_source_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${fcd_srcs})
+
+if(ENABLE_FCD)
+list(APPEND gr_osmosdr_libs ${GNURADIO_FCD_LIBRARIES})
+endif(ENABLE_FCD)
+
+if(ENABLE_FCDPP)
+list(APPEND gr_osmosdr_libs ${GNURADIO_FCDPP_LIBRARIES})
+endif(ENABLE_FCDPP)
diff --git a/lib/fcd/fcd_source_c.cc b/lib/fcd/fcd_source_c.cc
index 854e4c0..885d514 100644
--- a/lib/fcd/fcd_source_c.cc
+++ b/lib/fcd/fcd_source_c.cc
@@ -23,6 +23,7 @@
#include <sstream>
#include <boost/assign.hpp>
+#include <boost/foreach.hpp>
#include <gnuradio/io_signature.h>
@@ -141,15 +142,18 @@ fcd_source_c::fcd_source_c(const std::string &args) :
std::cerr << "Using " << name() << " (" << dev_name << ")" << std::endl;
+#ifdef HAVE_FCD
if ( FUNCUBE_V1 == _type )
{
- _src_v1 = gr::fcdproplus::fcd::make( dev_name );
+ _src_v1 = gr::fcd::source_c::make( dev_name );
connect( _src_v1, 0, self(), 0 );
set_gain( 20, "LNA" );
set_gain( 12, "MIX" );
}
+#endif
+#ifdef HAVE_FCDPP
if ( FUNCUBE_V2 == _type )
{
_src_v2 = gr::fcdproplus::fcdproplus::make( dev_name );
@@ -159,6 +163,7 @@ fcd_source_c::fcd_source_c(const std::string &args) :
set_gain( 1, "MIX" );
set_gain( 15, "BB" );
}
+#endif
}
fcd_source_c::~fcd_source_c()
@@ -170,7 +175,7 @@ std::vector< std::string > fcd_source_c::get_devices()
int id = 0;
std::vector< std::string > devices;
- for (device_t dev : _get_devices())
+ BOOST_FOREACH( device_t dev, _get_devices() )
{
std::string args = "fcd=" + boost::lexical_cast< std::string >( id++ );
@@ -236,11 +241,15 @@ osmosdr::freq_range_t fcd_source_c::get_freq_range( size_t chan )
double fcd_source_c::set_center_freq( double freq, size_t chan )
{
+#ifdef HAVE_FCD
if ( FUNCUBE_V1 == _type )
_src_v1->set_freq( float(freq) );
+#endif
+#ifdef HAVE_FCDPP
if ( FUNCUBE_V2 == _type )
_src_v2->set_freq( float(freq) );
+#endif
_freq = freq;
@@ -254,11 +263,15 @@ double fcd_source_c::get_center_freq( size_t chan )
double fcd_source_c::set_freq_corr( double ppm, size_t chan )
{
+#ifdef HAVE_FCD
if ( FUNCUBE_V1 == _type )
_src_v1->set_freq_corr( ppm );
+#endif
+#ifdef HAVE_FCDPP
if ( FUNCUBE_V2 == _type )
_src_v2->set_freq_corr( ppm );
+#endif
_correct = ppm;
@@ -330,6 +343,7 @@ double fcd_source_c::set_gain( double gain, size_t chan )
double fcd_source_c::set_gain( double gain, const std::string & name, size_t chan )
{
+#ifdef HAVE_FCD
if ( FUNCUBE_V1 == _type )
{
if ( "LNA" == name )
@@ -343,7 +357,9 @@ double fcd_source_c::set_gain( double gain, const std::string & name, size_t cha
_src_v1->set_mixer_gain(_mix_gain);
}
}
+#endif
+#ifdef HAVE_FCDPP
if ( FUNCUBE_V2 == _type )
{
if ( "LNA" == name )
@@ -362,6 +378,7 @@ double fcd_source_c::set_gain( double gain, const std::string & name, size_t cha
_src_v2->set_if_gain(_bb_gain);
}
}
+#endif
return get_gain( name, chan );
}
diff --git a/lib/fcd/fcd_source_c.h b/lib/fcd/fcd_source_c.h
index 2b02eb1..70239f8 100644
--- a/lib/fcd/fcd_source_c.h
+++ b/lib/fcd/fcd_source_c.h
@@ -22,8 +22,13 @@
#include <gnuradio/hier_block2.h>
-#include <fcdproplus/fcd.h>
+#ifdef HAVE_FCD
+#include <gnuradio/fcd/source_c.h>
+#endif
+
+#ifdef HAVE_FCDPP
#include <fcdproplus/fcdproplus.h>
+#endif
#include "source_iface.h"
@@ -81,8 +86,12 @@ public:
private:
dongle_type _type;
- gr::fcdproplus::fcd::sptr _src_v1;
+#ifdef HAVE_FCD
+ gr::fcd::source_c::sptr _src_v1;
+#endif
+#ifdef HAVE_FCDPP
gr::fcdproplus::fcdproplus::sptr _src_v2;
+#endif
double _lna_gain, _mix_gain, _bb_gain, _freq;
int _correct;
};
diff --git a/lib/file/CMakeLists.txt b/lib/file/CMakeLists.txt
index c96632d..6c55e85 100644
--- a/lib/file/CMakeLists.txt
+++ b/lib/file/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,17 +21,18 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
-APPEND_LIB_LIST(
- gnuradio::gnuradio-blocks
-)
-message(STATUS ${gnuradio-blocks_LIBRARIES})
-
-list(APPEND gr_osmosdr_srcs
+set(file_srcs
${CMAKE_CURRENT_SOURCE_DIR}/file_source_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/file_sink_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${file_srcs})
+#list(APPEND gr_osmosdr_libs ${GNURADIO_BLOCKS_LIBRARIES})
+
diff --git a/lib/freesrp/CMakeLists.txt b/lib/freesrp/CMakeLists.txt
index aca0d8c..46df7e4 100644
--- a/lib/freesrp/CMakeLists.txt
+++ b/lib/freesrp/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,18 +21,19 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${LIBFREESRP_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- ${LIBFREESRP_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(freesrp_srcs
${CMAKE_CURRENT_SOURCE_DIR}/freesrp_common.cc
${CMAKE_CURRENT_SOURCE_DIR}/freesrp_source_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/freesrp_sink_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${freesrp_srcs})
+list(APPEND gr_osmosdr_libs ${LIBFREESRP_LIBRARIES})
diff --git a/lib/freesrp/freesrp_common.cc b/lib/freesrp/freesrp_common.cc
index 57bbdbb..d60fbb8 100644
--- a/lib/freesrp/freesrp_common.cc
+++ b/lib/freesrp/freesrp_common.cc
@@ -2,6 +2,7 @@
#include <cstdlib>
+#include <boost/make_shared.hpp>
#include <boost/assign.hpp>
#include <arg_helpers.h>
@@ -10,7 +11,7 @@ using namespace FreeSRP;
using namespace std;
using namespace boost::assign;
-std::shared_ptr<::FreeSRP::FreeSRP> freesrp_common::_srp;
+boost::shared_ptr<::FreeSRP::FreeSRP> freesrp_common::_srp;
freesrp_common::freesrp_common(const string &args)
{
diff --git a/lib/freesrp/freesrp_common.h b/lib/freesrp/freesrp_common.h
index 8d13c47..9a5687c 100644
--- a/lib/freesrp/freesrp_common.h
+++ b/lib/freesrp/freesrp_common.h
@@ -1,7 +1,6 @@
#ifndef INCLUDED_FREESRP_COMMON_H
#define INCLUDED_FREESRP_COMMON_H
-#include <memory>
#include <vector>
#include <string>
@@ -23,7 +22,7 @@ public:
double set_freq_corr( double ppm, size_t chan = 0 );
double get_freq_corr( size_t chan = 0 );
protected:
- static std::shared_ptr<::FreeSRP::FreeSRP> _srp;
+ static boost::shared_ptr<::FreeSRP::FreeSRP> _srp;
bool _ignore_overflow = false;
};
diff --git a/lib/gnuradio-osmosdr.rc.in b/lib/gnuradio-osmosdr.rc.in
new file mode 100644
index 0000000..62fd5ea
--- /dev/null
+++ b/lib/gnuradio-osmosdr.rc.in
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <afxres.h>
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @MAJOR_VERSION@,@API_COMPAT@,@RC_MINOR_VERSION@,@RC_MAINT_VERSION@
+ PRODUCTVERSION @MAJOR_VERSION@,@API_COMPAT@,@RC_MINOR_VERSION@,@RC_MAINT_VERSION@
+ FILEFLAGSMASK 0x3fL
+#ifndef NDEBUG
+ FILEFLAGS 0x0L
+#else
+ FILEFLAGS 0x1L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE VFT2_DRV_INSTALLABLE
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "gnuradio-osmosdr"
+ VALUE "FileVersion", "@VERSION@"
+ VALUE "InternalName", "gnuradio-osmosdr.dll"
+ VALUE "LegalCopyright", "Licensed under GPLv3 or any later version"
+ VALUE "OriginalFilename", "gnuradio-osmosdr.dll"
+ VALUE "ProductName", "gnuradio-osmosdr"
+ VALUE "ProductVersion", "@VERSION@"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+ END
diff --git a/lib/hackrf/CMakeLists.txt b/lib/hackrf/CMakeLists.txt
index a0ec70a..c7af0c9 100644
--- a/lib/hackrf/CMakeLists.txt
+++ b/lib/hackrf/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,18 +21,27 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${LIBHACKRF_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- ${LIBHACKRF_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
- ${CMAKE_CURRENT_SOURCE_DIR}/hackrf_common.cc
+set(hackrf_srcs
${CMAKE_CURRENT_SOURCE_DIR}/hackrf_source_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/hackrf_sink_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+INCLUDE(CheckFunctionExists)
+set(CMAKE_REQUIRED_LIBRARIES ${LIBHACKRF_LIBRARIES})
+CHECK_FUNCTION_EXISTS(hackrf_device_list LIBHACKRF_HAVE_DEVICE_LIST)
+
+if(LIBHACKRF_HAVE_DEVICE_LIST)
+ message(STATUS "HackRF multiple device support enabled")
+ add_definitions(-DLIBHACKRF_HAVE_DEVICE_LIST)
+endif(LIBHACKRF_HAVE_DEVICE_LIST)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${hackrf_srcs})
+list(APPEND gr_osmosdr_libs ${LIBHACKRF_LIBRARIES})
diff --git a/lib/hackrf/hackrf_common.cc b/lib/hackrf/hackrf_common.cc
deleted file mode 100644
index 666dc60..0000000
--- a/lib/hackrf/hackrf_common.cc
+++ /dev/null
@@ -1,427 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2020 Clayton Smith <argilo@gmail.com>
- *
- * gr-osmosdr is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * gr-osmosdr 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with gr-osmosdr; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "hackrf_common.h"
-
-#include "arg_helpers.h"
-
-int hackrf_common::_usage = 0;
-std::mutex hackrf_common::_usage_mutex;
-
-std::map<std::string, std::weak_ptr<hackrf_device>> hackrf_common::_devs;
-std::mutex hackrf_common::_devs_mutex;
-
-hackrf_common::hackrf_common(const std::string &args) :
- _dev(NULL),
- _sample_rate(0),
- _center_freq(0),
- _freq_corr(0),
- _auto_gain(false),
- _requested_bandwidth(0),
- _bandwidth(0),
- _bias(false),
- _started(false)
-{
- int ret;
- hackrf_device *raw_dev;
- hackrf_device_list_t *list;
- int dev_index;
- std::string target_serial = "0";
- std::string final_serial = "";
-
- dict_t dict = params_to_dict(args);
- if (dict.count("hackrf") > 0 && dict["hackrf"].length() > 0) {
- target_serial = dict["hackrf"];
- }
-
- {
- std::lock_guard<std::mutex> guard(_usage_mutex);
-
- if (_usage == 0) {
- hackrf_init(); /* call only once before the first open */
- }
-
- _usage++;
- }
-
- list = hackrf_device_list();
-
- if (target_serial.length() > 1) {
- for (dev_index = 0; dev_index < list->devicecount; dev_index++) {
- if (list->serial_numbers[dev_index]) {
- std::string serial(list->serial_numbers[dev_index]);
- if (serial.compare(serial.length() - target_serial.length(),
- target_serial.length(), target_serial) == 0) {
- break;
- }
- }
- }
-
- if (dev_index >= list->devicecount) {
- hackrf_device_list_free(list);
- throw std::runtime_error(
- "No device found with serial number '" + target_serial + "'");
- }
- } else {
- try {
- dev_index = std::stoi(target_serial);
- } catch (std::exception &ex) {
- hackrf_device_list_free(list);
- throw std::runtime_error(
- "Failed to use '" + target_serial + "' as HackRF device index number");
- }
-
- if (dev_index >= list->devicecount) {
- hackrf_device_list_free(list);
- throw std::runtime_error(
- "Failed to use '" + target_serial + "' as HackRF device index: not enough devices");
- }
- }
-
- if (list->serial_numbers[dev_index]) {
- final_serial = list->serial_numbers[dev_index];
- }
-
- {
- std::lock_guard<std::mutex> guard(_devs_mutex);
-
- if (_devs.count(final_serial) > 0 && !_devs[final_serial].expired()) {
- _dev = hackrf_sptr(_devs[final_serial]);
- } else {
- ret = hackrf_device_list_open(list, dev_index, &raw_dev);
- HACKRF_THROW_ON_ERROR(ret, "Failed to open HackRF device")
- _dev = hackrf_sptr(raw_dev, hackrf_common::close);
- _devs[final_serial] = static_cast<std::weak_ptr<struct hackrf_device>>(_dev);
- }
- }
-
- hackrf_device_list_free(list);
-
- uint8_t board_id;
- ret = hackrf_board_id_read(_dev.get(), &board_id);
- HACKRF_THROW_ON_ERROR(ret, "Failed to get HackRF board id")
-
- char version[40];
- memset(version, 0, sizeof(version));
- ret = hackrf_version_string_read(_dev.get(), version, sizeof(version));
- HACKRF_THROW_ON_ERROR(ret, "Failed to read version string")
-
- std::cerr << "Using " << hackrf_board_id_name(hackrf_board_id(board_id)) << " "
- << "with firmware " << version
- << std::endl;
-}
-
-void hackrf_common::close(void *dev)
-{
- int ret = hackrf_close(static_cast<hackrf_device *>(dev));
- if (ret != HACKRF_SUCCESS)
- {
- std::cerr << HACKRF_FORMAT_ERROR(ret, "Failed to close HackRF") << std::endl;
- }
-
- {
- std::lock_guard<std::mutex> guard(_usage_mutex);
-
- _usage--;
-
- if (_usage == 0) {
- hackrf_exit(); /* call only once after last close */
- }
- }
-}
-
-std::vector<std::string> hackrf_common::get_devices()
-{
- std::vector<std::string> devices;
- std::string label;
-
- {
- std::lock_guard<std::mutex> guard(_usage_mutex);
-
- if (_usage == 0) {
- hackrf_init(); /* call only once before the first open */
- }
-
- _usage++;
- }
-
- hackrf_device_list_t *list = hackrf_device_list();
-
- for (int i = 0; i < list->devicecount; i++) {
- label = "HackRF ";
- label += hackrf_usb_board_id_name(list->usb_board_ids[i]);
-
- std::string args;
- if (list->serial_numbers[i]) {
- std::string serial(list->serial_numbers[i]);
- if (serial.length() > 6)
- serial = serial.substr(serial.length() - 6, 6);
- args = "hackrf=" + serial;
- if (serial.length() )
- label += " " + serial;
- } else {
- args = "hackrf"; /* will pick the first one, serial number is required for choosing a specific one */
- }
-
- args += ",label='" + label + "'";
- devices.push_back(args);
- }
-
- hackrf_device_list_free(list);
-
- {
- std::lock_guard<std::mutex> guard(_usage_mutex);
-
- _usage--;
-
- if (_usage == 0) {
- hackrf_exit(); /* call only once after last close */
- }
- }
-
- return devices;
-}
-
-osmosdr::meta_range_t hackrf_common::get_sample_rates()
-{
- osmosdr::meta_range_t range;
-
- /* we only add integer rates here because of better phase noise performance.
- * the user is allowed to request arbitrary (fractional) rates within these
- * boundaries. */
-
- range.push_back(osmosdr::range_t( 8e6 ));
- range.push_back(osmosdr::range_t( 10e6 ));
- range.push_back(osmosdr::range_t( 12.5e6 ));
- range.push_back(osmosdr::range_t( 16e6 ));
- range.push_back(osmosdr::range_t( 20e6 )); /* confirmed to work on fast machines */
-
- return range;
-}
-
-double hackrf_common::set_sample_rate( double rate )
-{
- int ret;
-
- if (_dev.get() && _started) {
- ret = hackrf_set_sample_rate( _dev.get(), rate );
- if ( HACKRF_SUCCESS != ret ) {
- HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
- }
- }
-
- _sample_rate = rate;
- return get_sample_rate();
-}
-
-double hackrf_common::get_sample_rate()
-{
- return _sample_rate;
-}
-
-osmosdr::freq_range_t hackrf_common::get_freq_range( size_t chan )
-{
- osmosdr::freq_range_t range;
-
- range.push_back(osmosdr::range_t( _sample_rate / 2, 7250e6 - _sample_rate / 2 ));
-
- return range;
-}
-
-double hackrf_common::set_center_freq( double freq, size_t chan )
-{
- int ret;
-
- #define APPLY_PPM_CORR(val, ppm) ((val) * (1.0 + (ppm) * 0.000001))
-
- if (_dev.get() && _started) {
- double corr_freq = APPLY_PPM_CORR( freq, _freq_corr );
- ret = hackrf_set_freq( _dev.get(), uint64_t(corr_freq) );
- if ( HACKRF_SUCCESS != ret ) {
- HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_freq", corr_freq ) )
- }
- }
-
- _center_freq = freq;
- return get_center_freq( chan );
-}
-
-double hackrf_common::get_center_freq( size_t chan )
-{
- return _center_freq;
-}
-
-double hackrf_common::set_freq_corr( double ppm, size_t chan )
-{
- _freq_corr = ppm;
-
- set_center_freq( _center_freq );
-
- return get_freq_corr( chan );
-}
-
-double hackrf_common::get_freq_corr( size_t chan )
-{
- return _freq_corr;
-}
-
-bool hackrf_common::set_gain_mode( bool automatic, size_t chan )
-{
- _auto_gain = automatic;
-
- return get_gain_mode(chan);
-}
-
-bool hackrf_common::get_gain_mode( size_t chan )
-{
- return _auto_gain;
-}
-
-double hackrf_common::set_gain( double gain, size_t chan )
-{
- int ret;
- double clip_gain = (gain >= 14.0) ? 14.0 : 0.0;
-
- if (_dev.get() && _started) {
- uint8_t value = (clip_gain == 14.0) ? 1 : 0;
-
- ret = hackrf_set_amp_enable( _dev.get(), value );
- if ( HACKRF_SUCCESS != ret ) {
- HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_amp_enable", value ) )
- }
- }
-
- _amp_gain = clip_gain;
- return hackrf_common::get_gain(chan);
-}
-
-double hackrf_common::get_gain( size_t chan )
-{
- return _amp_gain;
-}
-
-std::vector< std::string > hackrf_common::get_antennas( size_t chan )
-{
- return { get_antenna( chan ) };
-}
-
-std::string hackrf_common::set_antenna( const std::string & antenna, size_t chan )
-{
- return get_antenna( chan );
-}
-
-std::string hackrf_common::get_antenna( size_t chan )
-{
- return "TX/RX";
-}
-
-double hackrf_common::set_bandwidth( double bandwidth, size_t chan )
-{
- int ret;
-// osmosdr::freq_range_t bandwidths = get_bandwidth_range( chan );
-
- _requested_bandwidth = bandwidth;
- if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */
- bandwidth = _sample_rate * 0.75; /* select narrower filters to prevent aliasing */
-
- /* compute best default value depending on sample rate (auto filter) */
- uint32_t bw = hackrf_compute_baseband_filter_bw( uint32_t(bandwidth) );
-
- if (_dev.get() && _started) {
- ret = hackrf_set_baseband_filter_bandwidth( _dev.get(), bw );
- if (HACKRF_SUCCESS != ret) {
- HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_baseband_filter_bandwidth", bw ) )
- }
- }
-
- _bandwidth = bw;
- return get_bandwidth(chan);
-}
-
-double hackrf_common::get_bandwidth( size_t chan )
-{
- return _bandwidth;
-}
-
-osmosdr::freq_range_t hackrf_common::get_bandwidth_range( size_t chan )
-{
- osmosdr::freq_range_t bandwidths;
-
- // TODO: read out from libhackrf when an API is available
-
- bandwidths.push_back(osmosdr::range_t( 1750000 ));
- bandwidths.push_back(osmosdr::range_t( 2500000 ));
- bandwidths.push_back(osmosdr::range_t( 3500000 ));
- bandwidths.push_back(osmosdr::range_t( 5000000 ));
- bandwidths.push_back(osmosdr::range_t( 5500000 ));
- bandwidths.push_back(osmosdr::range_t( 6000000 ));
- bandwidths.push_back(osmosdr::range_t( 7000000 ));
- bandwidths.push_back(osmosdr::range_t( 8000000 ));
- bandwidths.push_back(osmosdr::range_t( 9000000 ));
- bandwidths.push_back(osmosdr::range_t( 10000000 ));
- bandwidths.push_back(osmosdr::range_t( 12000000 ));
- bandwidths.push_back(osmosdr::range_t( 14000000 ));
- bandwidths.push_back(osmosdr::range_t( 15000000 ));
- bandwidths.push_back(osmosdr::range_t( 20000000 ));
- bandwidths.push_back(osmosdr::range_t( 24000000 ));
- bandwidths.push_back(osmosdr::range_t( 28000000 ));
-
- return bandwidths;
-}
-
-bool hackrf_common::set_bias( bool bias )
-{
- int ret;
-
- if (_dev.get() && _started) {
- ret = hackrf_set_antenna_enable(_dev.get(), static_cast<uint8_t>(bias));
- if (ret != HACKRF_SUCCESS)
- {
- std::cerr << "Failed to apply antenna bias voltage state: " << bias << HACKRF_FORMAT_ERROR(ret, "") << std::endl;
- }
- }
-
- _bias = bias;
- return get_bias();
-}
-
-bool hackrf_common::get_bias()
-{
- return _bias;
-}
-
-void hackrf_common::start()
-{
- _started = true;
- set_center_freq(get_center_freq());
- set_sample_rate(get_sample_rate());
- if (_requested_bandwidth != 0)
- set_bandwidth(get_bandwidth());
- set_gain(get_gain());
- set_bias(get_bias());
-}
-
-void hackrf_common::stop()
-{
- _started = false;
-}
diff --git a/lib/hackrf/hackrf_common.h b/lib/hackrf/hackrf_common.h
deleted file mode 100644
index d1ab47b..0000000
--- a/lib/hackrf/hackrf_common.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2020 Clayton Smith <argilo@gmail.com>
- *
- * gr-osmosdr is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * gr-osmosdr 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with gr-osmosdr; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-#ifndef INCLUDED_HACKRF_COMMON_H
-#define INCLUDED_HACKRF_COMMON_H
-
-#include <map>
-#include <memory>
-#include <mutex>
-#include <string>
-#include <vector>
-
-#include <boost/format.hpp>
-
-#include <osmosdr/ranges.h>
-#include <libhackrf/hackrf.h>
-
-#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
-#define BUF_NUM 15
-
-#define BYTES_PER_SAMPLE 2 /* HackRF device produces/consumes 8 bit signed IQ data */
-
-#define HACKRF_FORMAT_ERROR(ret, msg) \
- boost::str( boost::format(msg " (%1%) %2%") \
- % ret % hackrf_error_name((enum hackrf_error)ret) )
-
-#define HACKRF_THROW_ON_ERROR(ret, msg) \
- if ( ret != HACKRF_SUCCESS ) \
- { \
- throw std::runtime_error( HACKRF_FORMAT_ERROR(ret, msg) ); \
- }
-
-#define HACKRF_FUNC_STR(func, arg) \
- boost::str(boost::format(func "(%1%)") % arg) + " has failed"
-
-typedef std::shared_ptr<hackrf_device> hackrf_sptr;
-
-class hackrf_common
-{
-public:
- hackrf_common(const std::string &args);
-
-protected:
- static std::vector< std::string > get_devices();
-
- osmosdr::meta_range_t get_sample_rates( void );
- double set_sample_rate( double rate );
- double get_sample_rate( void );
-
- osmosdr::freq_range_t get_freq_range( size_t chan = 0 );
- double set_center_freq( double freq, size_t chan = 0 );
- double get_center_freq( size_t chan = 0 );
- double set_freq_corr( double ppm, size_t chan = 0 );
- double get_freq_corr( size_t chan = 0 );
-
- bool set_gain_mode( bool automatic, size_t chan = 0 );
- bool get_gain_mode( size_t chan = 0 );
- double set_gain( double gain, size_t chan = 0 );
- double get_gain( size_t chan = 0 );
-
- std::vector< std::string > get_antennas( size_t chan = 0 );
- std::string set_antenna( const std::string & antenna, size_t chan = 0 );
- std::string get_antenna( size_t chan = 0 );
-
- double set_bandwidth( double bandwidth, size_t chan = 0 );
- double get_bandwidth( size_t chan = 0 );
- osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
-
- bool set_bias( bool bias );
- bool get_bias();
-
- void start();
- void stop();
-
- hackrf_sptr _dev;
-
-private:
- static void close(void *dev);
-
- static int _usage;
- static std::mutex _usage_mutex;
-
- static std::map<std::string, std::weak_ptr<hackrf_device>> _devs;
- static std::mutex _devs_mutex;
-
- double _sample_rate;
- double _center_freq;
- double _freq_corr;
- bool _auto_gain;
- double _amp_gain;
- double _requested_bandwidth;
- double _bandwidth;
- bool _bias;
- bool _started;
-};
-
-#endif /* INCLUDED_HACKRF_COMMON_H */
diff --git a/lib/hackrf/hackrf_sink_c.cc b/lib/hackrf/hackrf_sink_c.cc
index 1762934..ee089c6 100644
--- a/lib/hackrf/hackrf_sink_c.cc
+++ b/lib/hackrf/hackrf_sink_c.cc
@@ -2,20 +2,19 @@
/*
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
* Copyright 2014 Hoernchen <la@tfc-server.de>
- * Copyright 2020 Clayton Smith <argilo@gmail.com>
*
- * gr-osmosdr is free software; you can redistribute it and/or modify
+ * GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
- * gr-osmosdr is distributed in the hope that it will be useful,
+ * GNU Radio 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with gr-osmosdr; see the file COPYING. If not, write to
+ * along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
@@ -38,12 +37,38 @@
#include <emmintrin.h>
#endif
+#include <boost/assign.hpp>
+#include <boost/format.hpp>
+#include <boost/detail/endian.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/thread/thread.hpp>
+
#include <gnuradio/io_signature.h>
#include "hackrf_sink_c.h"
#include "arg_helpers.h"
+using namespace boost::assign;
+
+#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
+#define BUF_NUM 15
+
+#define BYTES_PER_SAMPLE 2 /* HackRF device consumes 8 bit unsigned IQ data */
+
+#define HACKRF_FORMAT_ERROR(ret, msg) \
+ boost::str( boost::format(msg " (%1%) %2%") \
+ % ret % hackrf_error_name((enum hackrf_error)ret) )
+
+#define HACKRF_THROW_ON_ERROR(ret, msg) \
+ if ( ret != HACKRF_SUCCESS ) \
+ { \
+ throw std::runtime_error( HACKRF_FORMAT_ERROR(ret, msg) ); \
+ }
+
+#define HACKRF_FUNC_STR(func, arg) \
+ boost::str(boost::format(func "(%1%)") % arg) + " has failed"
+
static inline bool cb_init(circular_buffer_t *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
@@ -78,11 +103,6 @@ static inline bool cb_has_room(circular_buffer_t *cb)
return true;
}
-static inline bool cb_is_empty(circular_buffer_t *cb)
-{
- return cb->count == 0;
-}
-
static inline bool cb_push_back(circular_buffer_t *cb, const void *item)
{
if(cb->count == cb->capacity)
@@ -107,6 +127,9 @@ static inline bool cb_pop_front(circular_buffer_t *cb, void *item)
return true;
}
+int hackrf_sink_c::_usage = 0;
+boost::mutex hackrf_sink_c::_usage_mutex;
+
hackrf_sink_c_sptr make_hackrf_sink_c (const std::string & args)
{
return gnuradio::get_initial_sptr(new hackrf_sink_c (args));
@@ -133,21 +156,66 @@ hackrf_sink_c::hackrf_sink_c (const std::string &args)
: gr::sync_block ("hackrf_sink_c",
gr::io_signature::make(MIN_IN, MAX_IN, sizeof (gr_complex)),
gr::io_signature::make(MIN_OUT, MAX_OUT, sizeof (gr_complex))),
- hackrf_common::hackrf_common(args),
+ _dev(NULL),
_buf(NULL),
- _vga_gain(0)
+ _sample_rate(0),
+ _center_freq(0),
+ _freq_corr(0),
+ _auto_gain(false),
+ _amp_gain(0),
+ _vga_gain(0),
+ _bandwidth(0)
{
+ int ret;
+ std::string *hackrf_serial = NULL;
+
dict_t dict = params_to_dict(args);
+ if (dict.count("hackrf") && dict["hackrf"].length() > 0)
+ hackrf_serial = &dict["hackrf"];
+
_buf_num = 0;
if (dict.count("buffers"))
- _buf_num = std::stoi(dict["buffers"]);
+ _buf_num = boost::lexical_cast< unsigned int >( dict["buffers"] );
if (0 == _buf_num)
_buf_num = BUF_NUM;
- _stopping = false;
+ {
+ boost::mutex::scoped_lock lock( _usage_mutex );
+
+ if ( _usage == 0 )
+ hackrf_init(); /* call only once before the first open */
+
+ _usage++;
+ }
+
+ _dev = NULL;
+#ifdef LIBHACKRF_HAVE_DEVICE_LIST
+ if ( hackrf_serial )
+ ret = hackrf_open_by_serial( hackrf_serial->c_str(), &_dev );
+ else
+#endif
+ ret = hackrf_open( &_dev );
+ HACKRF_THROW_ON_ERROR(ret, "Failed to open HackRF device")
+
+ uint8_t board_id;
+ ret = hackrf_board_id_read( _dev, &board_id );
+ HACKRF_THROW_ON_ERROR(ret, "Failed to get HackRF board id")
+
+ char version[40];
+ memset(version, 0, sizeof(version));
+ ret = hackrf_version_string_read( _dev, version, sizeof(version));
+ HACKRF_THROW_ON_ERROR(ret, "Failed to read version string")
+#if 0
+ read_partid_serialno_t serial_number;
+ ret = hackrf_board_partid_serialno_read( _dev, &serial_number );
+ HACKRF_THROW_ON_ERROR(ret, "Failed to read serial number")
+#endif
+ std::cerr << "Using " << hackrf_board_id_name(hackrf_board_id(board_id)) << " "
+ << "with firmware " << version << " "
+ << std::endl;
if ( BUF_NUM != _buf_num ) {
std::cerr << "Using " << _buf_num << " buffers of size " << BUF_LEN << "."
@@ -164,12 +232,26 @@ hackrf_sink_c::hackrf_sink_c (const std::string &args)
// Check device args to find out if bias/phantom power is desired.
if ( dict.count("bias_tx") ) {
- hackrf_common::set_bias(dict["bias_tx"] == "1");
+ bool bias = boost::lexical_cast<bool>( dict["bias_tx"] );
+ ret = hackrf_set_antenna_enable(_dev, static_cast<uint8_t>(bias));
+ if ( ret != HACKRF_SUCCESS )
+ {
+ std::cerr << "Failed to apply antenna bias voltage state: " << bias << HACKRF_FORMAT_ERROR(ret, "") << std::endl;
+ }
+ else
+ {
+ std::cerr << (bias ? "Enabled" : "Disabled") << " antenna bias voltage" << std::endl;
+ }
}
_buf = (int8_t *) malloc( BUF_LEN );
cb_init( &_cbuf, _buf_num, BUF_LEN );
+
+// _thread = gr::thread::thread(_hackrf_wait, this);
+
+ ret = hackrf_start_tx( _dev, _hackrf_tx_callback, (void *)this );
+ HACKRF_THROW_ON_ERROR(ret, "Failed to start TX streaming")
}
/*
@@ -177,6 +259,30 @@ hackrf_sink_c::hackrf_sink_c (const std::string &args)
*/
hackrf_sink_c::~hackrf_sink_c ()
{
+ if (_dev) {
+// _thread.join();
+ int ret = hackrf_stop_tx( _dev );
+ if ( ret != HACKRF_SUCCESS )
+ {
+ std::cerr << HACKRF_FORMAT_ERROR(ret, "Failed to stop TX streaming") << std::endl;
+ }
+ ret = hackrf_close( _dev );
+ if ( ret != HACKRF_SUCCESS )
+ {
+ std::cerr << HACKRF_FORMAT_ERROR(ret, "Failed to close HackRF") << std::endl;
+ }
+ _dev = NULL;
+
+ {
+ boost::mutex::scoped_lock lock( _usage_mutex );
+
+ _usage--;
+
+ if ( _usage == 0 )
+ hackrf_exit(); /* call only once after last close */
+ }
+ }
+
free(_buf);
_buf = NULL;
@@ -196,16 +302,11 @@ int hackrf_sink_c::hackrf_tx_callback(unsigned char *buffer, uint32_t length)
*buffer++ = rand() % 255;
#else
{
- std::lock_guard<std::mutex> lock(_buf_mutex);
+ boost::mutex::scoped_lock lock( _buf_mutex );
if ( ! cb_pop_front( &_cbuf, buffer ) ) {
memset(buffer, 0, length);
- if (_stopping) {
- _buf_cond.notify_one();
- return -1;
- } else {
- std::cerr << "U" << std::flush;
- }
+ std::cerr << "U" << std::flush;
} else {
// std::cerr << "-" << std::flush;
_buf_cond.notify_one();
@@ -215,61 +316,42 @@ int hackrf_sink_c::hackrf_tx_callback(unsigned char *buffer, uint32_t length)
return 0; // TODO: return -1 on error/stop
}
+void hackrf_sink_c::_hackrf_wait(hackrf_sink_c *obj)
+{
+ obj->hackrf_wait();
+}
+
+void hackrf_sink_c::hackrf_wait()
+{
+}
+
bool hackrf_sink_c::start()
{
- if ( ! _dev.get() )
+ if ( ! _dev )
return false;
- _stopping = false;
_buf_used = 0;
- hackrf_common::start();
- int ret = hackrf_start_tx( _dev.get(), _hackrf_tx_callback, (void *)this );
+#if 0
+ int ret = hackrf_start_tx( _dev, _hackrf_tx_callback, (void *)this );
if ( ret != HACKRF_SUCCESS ) {
std::cerr << "Failed to start TX streaming (" << ret << ")" << std::endl;
return false;
}
+#endif
return true;
}
bool hackrf_sink_c::stop()
{
- int i;
-
- if ( ! _dev.get() )
+ if ( ! _dev )
return false;
-
- {
- std::unique_lock<std::mutex> lock(_buf_mutex);
-
- while ( ! cb_has_room(&_cbuf) )
- _buf_cond.wait( lock );
-
- // Fill the rest of the current buffer with silence.
- memset(_buf + _buf_used, 0, BUF_LEN - _buf_used);
- cb_push_back( &_cbuf, _buf );
- _buf_used = 0;
-
- // Add some more silence so the end doesn't get cut off.
- memset(_buf, 0, BUF_LEN);
- for (i = 0; i < 5; i++) {
- while ( ! cb_has_room(&_cbuf) )
- _buf_cond.wait( lock );
-
- cb_push_back( &_cbuf, _buf );
- }
-
- _stopping = true;
-
- while (hackrf_is_streaming(_dev.get()) == HACKRF_TRUE)
- _buf_cond.wait( lock );
- }
-
- hackrf_common::stop();
- int ret = hackrf_stop_tx( _dev.get() );
+#if 0
+ int ret = hackrf_stop_tx( _dev );
if ( ret != HACKRF_SUCCESS ) {
std::cerr << "Failed to stop TX streaming (" << ret << ")" << std::endl;
return false;
}
+#endif
return true;
}
@@ -342,7 +424,7 @@ int hackrf_sink_c::work( int noutput_items,
const gr_complex *in = (const gr_complex *) input_items[0];
{
- std::unique_lock<std::mutex> lock(_buf_mutex);
+ boost::mutex::scoped_lock lock( _buf_mutex );
while ( ! cb_has_room(&_cbuf) )
_buf_cond.wait( lock );
@@ -372,7 +454,7 @@ int hackrf_sink_c::work( int noutput_items,
if((unsigned int)noutput_items >= remaining) {
{
- std::lock_guard<std::mutex> lock(_buf_mutex);
+ boost::mutex::scoped_lock lock( _buf_mutex );
if ( ! cb_push_back( &_cbuf, _buf ) ) {
_buf_used = prev_buf_used;
@@ -395,7 +477,78 @@ int hackrf_sink_c::work( int noutput_items,
std::vector<std::string> hackrf_sink_c::get_devices()
{
- return hackrf_common::get_devices();
+ std::vector<std::string> devices;
+ std::string label;
+
+ {
+ boost::mutex::scoped_lock lock( _usage_mutex );
+
+ if ( _usage == 0 )
+ hackrf_init(); /* call only once before the first open */
+
+ _usage++;
+ }
+
+#ifdef LIBHACKRF_HAVE_DEVICE_LIST
+ hackrf_device_list_t *list = hackrf_device_list();
+
+ for (int i = 0; i < list->devicecount; i++) {
+ label = "HackRF ";
+ label += hackrf_usb_board_id_name( list->usb_board_ids[i] );
+
+ std::string args;
+ if (list->serial_numbers[i]) {
+ std::string serial = boost::lexical_cast< std::string >( list->serial_numbers[i] );
+ if (serial.length() > 6)
+ serial = serial.substr(serial.length() - 6, 6);
+ args = "hackrf=" + serial;
+ label += " " + serial;
+ } else
+ args = "hackrf"; /* will pick the first one, serial number is required for choosing a specific one */
+
+ boost::algorithm::trim(label);
+
+ args += ",label='" + label + "'";
+ devices.push_back( args );
+ }
+
+ hackrf_device_list_free(list);
+#else
+
+ int ret;
+ hackrf_device *dev = NULL;
+ ret = hackrf_open(&dev);
+ if ( HACKRF_SUCCESS == ret )
+ {
+ std::string args = "hackrf=0";
+
+ label = "HackRF";
+
+ uint8_t board_id;
+ ret = hackrf_board_id_read( dev, &board_id );
+ if ( HACKRF_SUCCESS == ret )
+ {
+ label += std::string(" ") + hackrf_board_id_name(hackrf_board_id(board_id));
+ }
+
+ args += ",label='" + label + "'";
+ devices.push_back( args );
+
+ ret = hackrf_close(dev);
+ }
+
+#endif
+
+ {
+ boost::mutex::scoped_lock lock( _usage_mutex );
+
+ _usage--;
+
+ if ( _usage == 0 )
+ hackrf_exit(); /* call only once after last close */
+ }
+
+ return devices;
}
size_t hackrf_sink_c::get_num_channels()
@@ -405,47 +558,98 @@ size_t hackrf_sink_c::get_num_channels()
osmosdr::meta_range_t hackrf_sink_c::get_sample_rates()
{
- return hackrf_common::get_sample_rates();
+ osmosdr::meta_range_t range;
+
+ /* we only add integer rates here because of better phase noise performance.
+ * the user is allowed to request arbitrary (fractional) rates within these
+ * boundaries. */
+
+ range += osmosdr::range_t( 8e6 );
+ range += osmosdr::range_t( 10e6 );
+ range += osmosdr::range_t( 12.5e6 );
+ range += osmosdr::range_t( 16e6 );
+ range += osmosdr::range_t( 20e6 ); /* confirmed to work on fast machines */
+
+ return range;
}
double hackrf_sink_c::set_sample_rate( double rate )
{
- return hackrf_common::set_sample_rate(rate);
+ int ret;
+
+ if (_dev) {
+ ret = hackrf_set_sample_rate( _dev, rate );
+ if ( HACKRF_SUCCESS == ret ) {
+ _sample_rate = rate;
+ //set_bandwidth( 0.0 ); /* bandwidth of 0 means automatic filter selection */
+ } else {
+ HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
+ }
+ }
+
+ return get_sample_rate();
}
double hackrf_sink_c::get_sample_rate()
{
- return hackrf_common::get_sample_rate();
+ return _sample_rate;
}
osmosdr::freq_range_t hackrf_sink_c::get_freq_range( size_t chan )
{
- return hackrf_common::get_freq_range(chan);
+ osmosdr::freq_range_t range;
+
+ range += osmosdr::range_t( _sample_rate / 2, 7250e6 - _sample_rate / 2 );
+
+ return range;
}
double hackrf_sink_c::set_center_freq( double freq, size_t chan )
{
- return hackrf_common::set_center_freq(freq, chan);
+ int ret;
+
+ #define APPLY_PPM_CORR(val, ppm) ((val) * (1.0 + (ppm) * 0.000001))
+
+ if (_dev) {
+ double corr_freq = APPLY_PPM_CORR( freq, _freq_corr );
+ ret = hackrf_set_freq( _dev, uint64_t(corr_freq) );
+ if ( HACKRF_SUCCESS == ret ) {
+ _center_freq = freq;
+ } else {
+ HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_freq", corr_freq ) )
+ }
+ }
+
+ return get_center_freq( chan );
}
double hackrf_sink_c::get_center_freq( size_t chan )
{
- return hackrf_common::get_center_freq(chan);
+ return _center_freq;
}
double hackrf_sink_c::set_freq_corr( double ppm, size_t chan )
{
- return hackrf_common::set_freq_corr(ppm, chan);
+ _freq_corr = ppm;
+
+ set_center_freq( _center_freq );
+
+ return get_freq_corr( chan );
}
double hackrf_sink_c::get_freq_corr( size_t chan )
{
- return hackrf_common::get_freq_corr(chan);
+ return _freq_corr;
}
std::vector<std::string> hackrf_sink_c::get_gain_names( size_t chan )
{
- return { "RF", "IF" };
+ std::vector< std::string > names;
+
+ names += "RF";
+ names += "IF";
+
+ return names;
}
osmosdr::gain_range_t hackrf_sink_c::get_gain_range( size_t chan )
@@ -468,17 +672,34 @@ osmosdr::gain_range_t hackrf_sink_c::get_gain_range( const std::string & name, s
bool hackrf_sink_c::set_gain_mode( bool automatic, size_t chan )
{
- return hackrf_common::set_gain_mode(automatic, chan);
+ _auto_gain = automatic;
+
+ return get_gain_mode(chan);
}
bool hackrf_sink_c::get_gain_mode( size_t chan )
{
- return hackrf_common::get_gain_mode(chan);
+ return _auto_gain;
}
double hackrf_sink_c::set_gain( double gain, size_t chan )
{
- return hackrf_common::set_gain(gain, chan);
+ int ret;
+ osmosdr::gain_range_t rf_gains = get_gain_range( "RF", chan );
+
+ if (_dev) {
+ double clip_gain = rf_gains.clip( gain, true );
+ uint8_t value = clip_gain == 14.0f ? 1 : 0;
+
+ ret = hackrf_set_amp_enable( _dev, value );
+ if ( HACKRF_SUCCESS == ret ) {
+ _amp_gain = clip_gain;
+ } else {
+ HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_amp_enable", value ) )
+ }
+ }
+
+ return _amp_gain;
}
double hackrf_sink_c::set_gain( double gain, const std::string & name, size_t chan)
@@ -496,7 +717,7 @@ double hackrf_sink_c::set_gain( double gain, const std::string & name, size_t ch
double hackrf_sink_c::get_gain( size_t chan )
{
- return hackrf_common::get_gain(chan);
+ return _amp_gain;
}
double hackrf_sink_c::get_gain( const std::string & name, size_t chan )
@@ -517,10 +738,10 @@ double hackrf_sink_c::set_if_gain( double gain, size_t chan )
int ret;
osmosdr::gain_range_t if_gains = get_gain_range( "IF", chan );
- if (_dev.get()) {
+ if (_dev) {
double clip_gain = if_gains.clip( gain, true );
- ret = hackrf_set_txvga_gain( _dev.get(), uint32_t(clip_gain) );
+ ret = hackrf_set_txvga_gain( _dev, uint32_t(clip_gain) );
if ( HACKRF_SUCCESS == ret ) {
_vga_gain = clip_gain;
} else {
@@ -538,30 +759,72 @@ double hackrf_sink_c::set_bb_gain( double gain, size_t chan )
std::vector< std::string > hackrf_sink_c::get_antennas( size_t chan )
{
- return hackrf_common::get_antennas(chan);
+ std::vector< std::string > antennas;
+
+ antennas += get_antenna( chan );
+
+ return antennas;
}
std::string hackrf_sink_c::set_antenna( const std::string & antenna, size_t chan )
{
- return hackrf_common::set_antenna(antenna, chan);
+ return get_antenna( chan );
}
std::string hackrf_sink_c::get_antenna( size_t chan )
{
- return hackrf_common::get_antenna(chan);
+ return "TX/RX";
}
double hackrf_sink_c::set_bandwidth( double bandwidth, size_t chan )
{
- return hackrf_common::set_bandwidth(bandwidth, chan);
+ int ret;
+// osmosdr::freq_range_t bandwidths = get_bandwidth_range( chan );
+
+ if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */
+ bandwidth = _sample_rate * 0.75; /* select narrower filters to prevent aliasing */
+
+ if ( _dev ) {
+ /* compute best default value depending on sample rate (auto filter) */
+ uint32_t bw = hackrf_compute_baseband_filter_bw( uint32_t(bandwidth) );
+ ret = hackrf_set_baseband_filter_bandwidth( _dev, bw );
+ if ( HACKRF_SUCCESS == ret ) {
+ _bandwidth = bw;
+ } else {
+ HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_baseband_filter_bandwidth", bw ) )
+ }
+ }
+
+ return _bandwidth;
}
double hackrf_sink_c::get_bandwidth( size_t chan )
{
- return hackrf_common::get_bandwidth(chan);
+ return _bandwidth;
}
osmosdr::freq_range_t hackrf_sink_c::get_bandwidth_range( size_t chan )
{
- return hackrf_common::get_bandwidth_range(chan);
+ osmosdr::freq_range_t bandwidths;
+
+ // TODO: read out from libhackrf when an API is available
+
+ bandwidths += osmosdr::range_t( 1750000 );
+ bandwidths += osmosdr::range_t( 2500000 );
+ bandwidths += osmosdr::range_t( 3500000 );
+ bandwidths += osmosdr::range_t( 5000000 );
+ bandwidths += osmosdr::range_t( 5500000 );
+ bandwidths += osmosdr::range_t( 6000000 );
+ bandwidths += osmosdr::range_t( 7000000 );
+ bandwidths += osmosdr::range_t( 8000000 );
+ bandwidths += osmosdr::range_t( 9000000 );
+ bandwidths += osmosdr::range_t( 10000000 );
+ bandwidths += osmosdr::range_t( 12000000 );
+ bandwidths += osmosdr::range_t( 14000000 );
+ bandwidths += osmosdr::range_t( 15000000 );
+ bandwidths += osmosdr::range_t( 20000000 );
+ bandwidths += osmosdr::range_t( 24000000 );
+ bandwidths += osmosdr::range_t( 28000000 );
+
+ return bandwidths;
}
diff --git a/lib/hackrf/hackrf_sink_c.h b/lib/hackrf/hackrf_sink_c.h
index 08ff2ca..a7e7ab8 100644
--- a/lib/hackrf/hackrf_sink_c.h
+++ b/lib/hackrf/hackrf_sink_c.h
@@ -1,35 +1,34 @@
/* -*- c++ -*- */
/*
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
- * Copyright 2020 Clayton Smith <argilo@gmail.com>
*
- * gr-osmosdr is free software; you can redistribute it and/or modify
+ * GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
- * gr-osmosdr is distributed in the hope that it will be useful,
+ * GNU Radio 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with gr-osmosdr; see the file COPYING. If not, write to
+ * along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_HACKRF_SINK_C_H
#define INCLUDED_HACKRF_SINK_C_H
+#include <gnuradio/thread/thread.h>
#include <gnuradio/sync_block.h>
-#include <condition_variable>
-#include <mutex>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <libhackrf/hackrf.h>
#include "sink_iface.h"
-#include "hackrf_common.h"
class hackrf_sink_c;
@@ -68,8 +67,7 @@ hackrf_sink_c_sptr make_hackrf_sink_c (const std::string & args = "");
class hackrf_sink_c :
public gr::sync_block,
- public sink_iface,
- protected hackrf_common
+ public sink_iface
{
private:
// The friend declaration allows hackrf_make_sink_c to
@@ -126,16 +124,29 @@ public:
private:
static int _hackrf_tx_callback(hackrf_transfer* transfer);
int hackrf_tx_callback(unsigned char *buffer, uint32_t length);
+ static void _hackrf_wait(hackrf_sink_c *obj);
+ void hackrf_wait();
+
+ static int _usage;
+ static boost::mutex _usage_mutex;
+
+ hackrf_device *_dev;
+// gr::thread::thread _thread;
circular_buffer_t _cbuf;
int8_t *_buf;
unsigned int _buf_num;
unsigned int _buf_used;
- bool _stopping;
- std::mutex _buf_mutex;
- std::condition_variable _buf_cond;
-
+ boost::mutex _buf_mutex;
+ boost::condition_variable _buf_cond;
+
+ double _sample_rate;
+ double _center_freq;
+ double _freq_corr;
+ bool _auto_gain;
+ double _amp_gain;
double _vga_gain;
+ double _bandwidth;
};
#endif /* INCLUDED_HACKRF_SINK_C_H */
diff --git a/lib/hackrf/hackrf_source_c.cc b/lib/hackrf/hackrf_source_c.cc
index 03ea3bd..30b63c7 100644
--- a/lib/hackrf/hackrf_source_c.cc
+++ b/lib/hackrf/hackrf_source_c.cc
@@ -1,20 +1,19 @@
/* -*- c++ -*- */
/*
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
- * Copyright 2020 Clayton Smith <argilo@gmail.com>
*
- * gr-osmosdr is free software; you can redistribute it and/or modify
+ * GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
- * gr-osmosdr is distributed in the hope that it will be useful,
+ * GNU Radio 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with gr-osmosdr; see the file COPYING. If not, write to
+ * along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
@@ -30,7 +29,12 @@
#include <stdexcept>
#include <iostream>
-#include <chrono>
+
+#include <boost/assign.hpp>
+#include <boost/format.hpp>
+#include <boost/detail/endian.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/thread/thread.hpp>
#include <gnuradio/io_signature.h>
@@ -38,6 +42,29 @@
#include "arg_helpers.h"
+using namespace boost::assign;
+
+#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
+#define BUF_NUM 15
+
+#define BYTES_PER_SAMPLE 2 /* HackRF device produces 8 bit unsigned IQ data */
+
+#define HACKRF_FORMAT_ERROR(ret, msg) \
+ boost::str( boost::format(msg " (%1%) %2%") \
+ % ret % hackrf_error_name((enum hackrf_error)ret) )
+
+#define HACKRF_THROW_ON_ERROR(ret, msg) \
+ if ( ret != HACKRF_SUCCESS ) \
+ { \
+ throw std::runtime_error( HACKRF_FORMAT_ERROR(ret, msg) ); \
+ }
+
+#define HACKRF_FUNC_STR(func, arg) \
+ boost::str(boost::format(func "(%1%)") % arg) + " has failed"
+
+int hackrf_source_c::_usage = 0;
+boost::mutex hackrf_source_c::_usage_mutex;
+
hackrf_source_c_sptr make_hackrf_source_c (const std::string & args)
{
return gnuradio::get_initial_sptr(new hackrf_source_c (args));
@@ -64,20 +91,29 @@ hackrf_source_c::hackrf_source_c (const std::string &args)
: gr::sync_block ("hackrf_source_c",
gr::io_signature::make(MIN_IN, MAX_IN, sizeof (gr_complex)),
gr::io_signature::make(MIN_OUT, MAX_OUT, sizeof (gr_complex))),
- hackrf_common::hackrf_common(args),
+ _dev(NULL),
_buf(NULL),
+ _sample_rate(0),
+ _center_freq(0),
+ _freq_corr(0),
+ _auto_gain(false),
+ _amp_gain(0),
_lna_gain(0),
- _vga_gain(0)
+ _vga_gain(0),
+ _bandwidth(0)
{
+ int ret;
+ std::string hackrf_serial;
+
dict_t dict = params_to_dict(args);
_buf_num = _buf_len = _buf_head = _buf_used = _buf_offset = 0;
if (dict.count("buffers"))
- _buf_num = std::stoi(dict["buffers"]);
+ _buf_num = boost::lexical_cast< unsigned int >( dict["buffers"] );
// if (dict.count("buflen"))
-// _buf_len = std::stoi(dict["buflen"]);
+// _buf_len = boost::lexical_cast< unsigned int >( dict["buflen"] );
if (0 == _buf_num)
_buf_num = BUF_NUM;
@@ -88,10 +124,76 @@ hackrf_source_c::hackrf_source_c (const std::string &args)
_samp_avail = _buf_len / BYTES_PER_SAMPLE;
// create a lookup table for gr_complex values
- for (unsigned int i = 0; i <= 0xff; i++) {
- _lut.push_back( float(int8_t(i)) * (1.0f/128.0f) );
+ for (unsigned int i = 0; i <= 0xffff; i++) {
+#ifdef BOOST_LITTLE_ENDIAN
+ _lut.push_back( gr_complex( (float(int8_t(i & 0xff))) * (1.0f/128.0f),
+ (float(int8_t(i >> 8))) * (1.0f/128.0f) ) );
+#else // BOOST_BIG_ENDIAN
+ _lut.push_back( gr_complex( (float(int8_t(i >> 8))) * (1.0f/128.0f),
+ (float(int8_t(i & 0xff))) * (1.0f/128.0f) ) );
+#endif
+ }
+
+ {
+ boost::mutex::scoped_lock lock( _usage_mutex );
+
+ if ( _usage == 0 )
+ hackrf_init(); /* call only once before the first open */
+
+ _usage++;
}
+ _dev = NULL;
+
+#ifdef LIBHACKRF_HAVE_DEVICE_LIST
+ if (dict.count("hackrf") && dict["hackrf"].length() > 0) {
+ hackrf_serial = dict["hackrf"];
+
+ if (hackrf_serial.length() > 1) {
+ ret = hackrf_open_by_serial( hackrf_serial.c_str(), &_dev );
+ } else {
+ int dev_index = 0;
+ try {
+ dev_index = boost::lexical_cast< int >( hackrf_serial );
+ } catch ( std::exception &ex ) {
+ throw std::runtime_error(
+ "Failed to use '" + hackrf_serial + "' as HackRF device index number: " + ex.what());
+ }
+
+ hackrf_device_list_t *list = hackrf_device_list();
+ if (dev_index < list->devicecount) {
+ ret = hackrf_device_list_open(list, dev_index, &_dev);
+ } else {
+ hackrf_device_list_free(list);
+ throw std::runtime_error(
+ "Failed to use '" + hackrf_serial + "' as HackRF device index: not enough devices");
+ }
+ hackrf_device_list_free(list);
+ }
+ } else
+#endif
+ ret = hackrf_open( &_dev );
+
+ HACKRF_THROW_ON_ERROR(ret, "Failed to open HackRF device")
+
+ uint8_t board_id;
+ ret = hackrf_board_id_read( _dev, &board_id );
+ HACKRF_THROW_ON_ERROR(ret, "Failed to get HackRF board id")
+
+ char version[40];
+ memset(version, 0, sizeof(version));
+ ret = hackrf_version_string_read( _dev, version, sizeof(version));
+ HACKRF_THROW_ON_ERROR(ret, "Failed to read version string")
+
+#if 0
+ read_partid_serialno_t serial_number;
+ ret = hackrf_board_partid_serialno_read( _dev, &serial_number );
+ HACKRF_THROW_ON_ERROR(ret, "Failed to read serial number")
+#endif
+ std::cerr << "Using " << hackrf_board_id_name(hackrf_board_id(board_id)) << " "
+ << "with firmware " << version << " "
+ << std::endl;
+
if ( BUF_NUM != _buf_num || BUF_LEN != _buf_len ) {
std::cerr << "Using " << _buf_num << " buffers of size " << _buf_len << "."
<< std::endl;
@@ -109,15 +211,29 @@ hackrf_source_c::hackrf_source_c (const std::string &args)
// Check device args to find out if bias/phantom power is desired.
if ( dict.count("bias") ) {
- hackrf_common::set_bias(dict["bias"] == "1");
+ bool bias = boost::lexical_cast<bool>( dict["bias"] );
+ ret = hackrf_set_antenna_enable(_dev, static_cast<uint8_t>(bias));
+ if ( ret != HACKRF_SUCCESS )
+ {
+ std::cerr << "Failed to apply antenna bias voltage state: " << bias << HACKRF_FORMAT_ERROR(ret, "") << std::endl;
+ }
+ else
+ {
+ std::cerr << (bias ? "Enabled" : "Disabled") << " antenna bias voltage" << std::endl;
+ }
}
- _buf = (unsigned char **) malloc(_buf_num * sizeof(unsigned char *));
+ _buf = (unsigned short **) malloc(_buf_num * sizeof(unsigned short *));
if (_buf) {
for(unsigned int i = 0; i < _buf_num; ++i)
- _buf[i] = (unsigned char *) malloc(_buf_len);
+ _buf[i] = (unsigned short *) malloc(_buf_len);
}
+
+// _thread = gr::thread::thread(_hackrf_wait, this);
+
+ ret = hackrf_start_rx( _dev, _hackrf_rx_callback, (void *)this );
+ HACKRF_THROW_ON_ERROR(ret, "Failed to start RX streaming")
}
/*
@@ -125,6 +241,30 @@ hackrf_source_c::hackrf_source_c (const std::string &args)
*/
hackrf_source_c::~hackrf_source_c ()
{
+ if (_dev) {
+// _thread.join();
+ int ret = hackrf_stop_rx( _dev );
+ if ( ret != HACKRF_SUCCESS )
+ {
+ std::cerr << HACKRF_FORMAT_ERROR(ret, "Failed to stop RX streaming") << std::endl;
+ }
+ ret = hackrf_close( _dev );
+ if ( ret != HACKRF_SUCCESS )
+ {
+ std::cerr << HACKRF_FORMAT_ERROR(ret, "Failed to close HackRF") << std::endl;
+ }
+ _dev = NULL;
+
+ {
+ boost::mutex::scoped_lock lock( _usage_mutex );
+
+ _usage--;
+
+ if ( _usage == 0 )
+ hackrf_exit(); /* call only once after last close */
+ }
+ }
+
if (_buf) {
for(unsigned int i = 0; i < _buf_num; ++i) {
free(_buf[i]);
@@ -144,7 +284,7 @@ int hackrf_source_c::_hackrf_rx_callback(hackrf_transfer *transfer)
int hackrf_source_c::hackrf_rx_callback(unsigned char *buf, uint32_t len)
{
{
- std::lock_guard<std::mutex> lock(_buf_mutex);
+ boost::mutex::scoped_lock lock( _buf_mutex );
int buf_tail = (_buf_head + _buf_used) % _buf_num;
memcpy(_buf[buf_tail], buf, len);
@@ -162,31 +302,40 @@ int hackrf_source_c::hackrf_rx_callback(unsigned char *buf, uint32_t len)
return 0; // TODO: return -1 on error/stop
}
+void hackrf_source_c::_hackrf_wait(hackrf_source_c *obj)
+{
+ obj->hackrf_wait();
+}
+
+void hackrf_source_c::hackrf_wait()
+{
+}
+
bool hackrf_source_c::start()
{
- if ( ! _dev.get() )
+ if ( ! _dev )
return false;
-
- hackrf_common::start();
- int ret = hackrf_start_rx( _dev.get(), _hackrf_rx_callback, (void *)this );
+#if 0
+ int ret = hackrf_start_rx( _dev, _hackrf_rx_callback, (void *)this );
if ( ret != HACKRF_SUCCESS ) {
std::cerr << "Failed to start RX streaming (" << ret << ")" << std::endl;
return false;
}
+#endif
return true;
}
bool hackrf_source_c::stop()
{
- if ( ! _dev.get() )
+ if ( ! _dev )
return false;
-
- hackrf_common::stop();
- int ret = hackrf_stop_rx( _dev.get() );
+#if 0
+ int ret = hackrf_stop_rx( _dev );
if ( ret != HACKRF_SUCCESS ) {
std::cerr << "Failed to stop RX streaming (" << ret << ")" << std::endl;
return false;
}
+#endif
return true;
}
@@ -198,41 +347,33 @@ int hackrf_source_c::work( int noutput_items,
bool running = false;
- if ( _dev.get() )
- running = (hackrf_is_streaming( _dev.get() ) == HACKRF_TRUE);
+ if ( _dev )
+ running = (hackrf_is_streaming( _dev ) == HACKRF_TRUE);
{
- std::unique_lock<std::mutex> lock(_buf_mutex);
+ boost::mutex::scoped_lock lock( _buf_mutex );
- while (_buf_used < 3 && running) { // collect at least 3 buffers
- _buf_cond.wait_for( lock , std::chrono::milliseconds(100));
-
- // Re-check whether the device has closed or stopped streaming
- if ( _dev.get() )
- running = (hackrf_is_streaming( _dev.get() ) == HACKRF_TRUE);
- else
- running = false;
- }
+ while (_buf_used < 3 && running) // collect at least 3 buffers
+ _buf_cond.wait( lock );
}
if ( ! running )
return WORK_DONE;
- const uint8_t *buf = _buf[_buf_head] + _buf_offset * BYTES_PER_SAMPLE;
-#define TO_COMPLEX(p) gr_complex( _lut[(p)[0]], _lut[(p)[1]] )
+ unsigned short *buf = _buf[_buf_head] + _buf_offset;
if (noutput_items <= _samp_avail) {
for (int i = 0; i < noutput_items; ++i)
- *out++ = TO_COMPLEX( buf + i*BYTES_PER_SAMPLE );
+ *out++ = _lut[ *(buf + i) ];
_buf_offset += noutput_items;
_samp_avail -= noutput_items;
} else {
for (int i = 0; i < _samp_avail; ++i)
- *out++ = TO_COMPLEX( buf + i*BYTES_PER_SAMPLE );
+ *out++ = _lut[ *(buf + i) ];
{
- std::lock_guard<std::mutex> lock(_buf_mutex);
+ boost::mutex::scoped_lock lock( _buf_mutex );
_buf_head = (_buf_head + 1) % _buf_num;
_buf_used--;
@@ -243,7 +384,7 @@ int hackrf_source_c::work( int noutput_items,
int remaining = noutput_items - _samp_avail;
for (int i = 0; i < remaining; ++i)
- *out++ = TO_COMPLEX( buf + i*BYTES_PER_SAMPLE );
+ *out++ = _lut[ *(buf + i) ];
_buf_offset = remaining;
_samp_avail = (_buf_len / BYTES_PER_SAMPLE) - remaining;
@@ -254,7 +395,78 @@ int hackrf_source_c::work( int noutput_items,
std::vector<std::string> hackrf_source_c::get_devices()
{
- return hackrf_common::get_devices();
+ std::vector<std::string> devices;
+ std::string label;
+
+ {
+ boost::mutex::scoped_lock lock( _usage_mutex );
+
+ if ( _usage == 0 )
+ hackrf_init(); /* call only once before the first open */
+
+ _usage++;
+ }
+
+#ifdef LIBHACKRF_HAVE_DEVICE_LIST
+ hackrf_device_list_t *list = hackrf_device_list();
+
+ for (int i = 0; i < list->devicecount; i++) {
+ label = "HackRF ";
+ label += hackrf_usb_board_id_name( list->usb_board_ids[i] );
+
+ std::string args;
+ if (list->serial_numbers[i]) {
+ std::string serial = boost::lexical_cast< std::string >( list->serial_numbers[i] );
+ if (serial.length() > 6)
+ serial = serial.substr(serial.length() - 6, 6);
+ args = "hackrf=" + serial;
+ label += " " + serial;
+ } else
+ args = "hackrf"; /* will pick the first one, serial number is required for choosing a specific one */
+
+ boost::algorithm::trim(label);
+
+ args += ",label='" + label + "'";
+ devices.push_back( args );
+ }
+
+ hackrf_device_list_free(list);
+#else
+
+ int ret;
+ hackrf_device *dev = NULL;
+ ret = hackrf_open(&dev);
+ if ( HACKRF_SUCCESS == ret )
+ {
+ std::string args = "hackrf=0";
+
+ label = "HackRF";
+
+ uint8_t board_id;
+ ret = hackrf_board_id_read( dev, &board_id );
+ if ( HACKRF_SUCCESS == ret )
+ {
+ label += std::string(" ") + hackrf_board_id_name(hackrf_board_id(board_id));
+ }
+
+ args += ",label='" + label + "'";
+ devices.push_back( args );
+
+ ret = hackrf_close(dev);
+ }
+
+#endif
+
+ {
+ boost::mutex::scoped_lock lock( _usage_mutex );
+
+ _usage--;
+
+ if ( _usage == 0 )
+ hackrf_exit(); /* call only once after last close */
+ }
+
+ return devices;
}
size_t hackrf_source_c::get_num_channels()
@@ -264,47 +476,99 @@ size_t hackrf_source_c::get_num_channels()
osmosdr::meta_range_t hackrf_source_c::get_sample_rates()
{
- return hackrf_common::get_sample_rates();
+ osmosdr::meta_range_t range;
+
+ /* we only add integer rates here because of better phase noise performance.
+ * the user is allowed to request arbitrary (fractional) rates within these
+ * boundaries. */
+
+ range += osmosdr::range_t( 8e6 );
+ range += osmosdr::range_t( 10e6 );
+ range += osmosdr::range_t( 12.5e6 );
+ range += osmosdr::range_t( 16e6 );
+ range += osmosdr::range_t( 20e6 ); /* confirmed to work on fast machines */
+
+ return range;
}
double hackrf_source_c::set_sample_rate( double rate )
{
- return hackrf_common::set_sample_rate(rate);
+ int ret;
+
+ if (_dev) {
+ ret = hackrf_set_sample_rate( _dev, rate );
+ if ( HACKRF_SUCCESS == ret ) {
+ _sample_rate = rate;
+ //set_bandwidth( 0.0 ); /* bandwidth of 0 means automatic filter selection */
+ } else {
+ HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
+ }
+ }
+
+ return get_sample_rate();
}
double hackrf_source_c::get_sample_rate()
{
- return hackrf_common::get_sample_rate();
+ return _sample_rate;
}
osmosdr::freq_range_t hackrf_source_c::get_freq_range( size_t chan )
{
- return hackrf_common::get_freq_range(chan);
+ osmosdr::freq_range_t range;
+
+ range += osmosdr::range_t( _sample_rate / 2, 7250e6 - _sample_rate / 2 );
+
+ return range;
}
double hackrf_source_c::set_center_freq( double freq, size_t chan )
{
- return hackrf_common::set_center_freq(freq, chan);
+ int ret;
+
+ #define APPLY_PPM_CORR(val, ppm) ((val) * (1.0 + (ppm) * 0.000001))
+
+ if (_dev) {
+ double corr_freq = APPLY_PPM_CORR( freq, _freq_corr );
+ ret = hackrf_set_freq( _dev, uint64_t(corr_freq) );
+ if ( HACKRF_SUCCESS == ret ) {
+ _center_freq = freq;
+ } else {
+ HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_freq", corr_freq ) )
+ }
+ }
+
+ return get_center_freq( chan );
}
double hackrf_source_c::get_center_freq( size_t chan )
{
- return hackrf_common::get_center_freq(chan);
+ return _center_freq;
}
double hackrf_source_c::set_freq_corr( double ppm, size_t chan )
{
- return hackrf_common::set_freq_corr(ppm, chan);
+ _freq_corr = ppm;
+
+ set_center_freq( _center_freq );
+
+ return get_freq_corr( chan );
}
double hackrf_source_c::get_freq_corr( size_t chan )
{
- return hackrf_common::get_freq_corr(chan);
+ return _freq_corr;
}
std::vector<std::string> hackrf_source_c::get_gain_names( size_t chan )
{
- return { "RF", "IF", "BB" };
+ std::vector< std::string > names;
+
+ names += "RF";
+ names += "IF";
+ names += "BB";
+
+ return names;
}
osmosdr::gain_range_t hackrf_source_c::get_gain_range( size_t chan )
@@ -331,17 +595,34 @@ osmosdr::gain_range_t hackrf_source_c::get_gain_range( const std::string & name,
bool hackrf_source_c::set_gain_mode( bool automatic, size_t chan )
{
- return hackrf_common::set_gain_mode(automatic, chan);
+ _auto_gain = automatic;
+
+ return get_gain_mode(chan);
}
bool hackrf_source_c::get_gain_mode( size_t chan )
{
- return hackrf_common::get_gain_mode(chan);
+ return _auto_gain;
}
double hackrf_source_c::set_gain( double gain, size_t chan )
{
- return hackrf_common::set_gain(gain, chan);
+ int ret;
+ osmosdr::gain_range_t rf_gains = get_gain_range( "RF", chan );
+
+ if (_dev) {
+ double clip_gain = rf_gains.clip( gain, true );
+ uint8_t value = clip_gain == 14.0f ? 1 : 0;
+
+ ret = hackrf_set_amp_enable( _dev, value );
+ if ( HACKRF_SUCCESS == ret ) {
+ _amp_gain = clip_gain;
+ } else {
+ HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_amp_enable", value ) )
+ }
+ }
+
+ return _amp_gain;
}
double hackrf_source_c::set_gain( double gain, const std::string & name, size_t chan)
@@ -363,7 +644,7 @@ double hackrf_source_c::set_gain( double gain, const std::string & name, size_t
double hackrf_source_c::get_gain( size_t chan )
{
- return hackrf_common::get_gain(chan);
+ return _amp_gain;
}
double hackrf_source_c::get_gain( const std::string & name, size_t chan )
@@ -388,10 +669,10 @@ double hackrf_source_c::set_if_gain(double gain, size_t chan)
int ret;
osmosdr::gain_range_t rf_gains = get_gain_range( "IF", chan );
- if (_dev.get()) {
+ if (_dev) {
double clip_gain = rf_gains.clip( gain, true );
- ret = hackrf_set_lna_gain( _dev.get(), uint32_t(clip_gain) );
+ ret = hackrf_set_lna_gain( _dev, uint32_t(clip_gain) );
if ( HACKRF_SUCCESS == ret ) {
_lna_gain = clip_gain;
} else {
@@ -407,10 +688,10 @@ double hackrf_source_c::set_bb_gain( double gain, size_t chan )
int ret;
osmosdr::gain_range_t if_gains = get_gain_range( "BB", chan );
- if (_dev.get()) {
+ if (_dev) {
double clip_gain = if_gains.clip( gain, true );
- ret = hackrf_set_vga_gain( _dev.get(), uint32_t(clip_gain) );
+ ret = hackrf_set_vga_gain( _dev, uint32_t(clip_gain) );
if ( HACKRF_SUCCESS == ret ) {
_vga_gain = clip_gain;
} else {
@@ -423,30 +704,72 @@ double hackrf_source_c::set_bb_gain( double gain, size_t chan )
std::vector< std::string > hackrf_source_c::get_antennas( size_t chan )
{
- return hackrf_common::get_antennas(chan);
+ std::vector< std::string > antennas;
+
+ antennas += get_antenna( chan );
+
+ return antennas;
}
std::string hackrf_source_c::set_antenna( const std::string & antenna, size_t chan )
{
- return hackrf_common::set_antenna(antenna, chan);
+ return get_antenna( chan );
}
std::string hackrf_source_c::get_antenna( size_t chan )
{
- return hackrf_common::get_antenna(chan);
+ return "TX/RX";
}
double hackrf_source_c::set_bandwidth( double bandwidth, size_t chan )
{
- return hackrf_common::set_bandwidth(bandwidth, chan);
+ int ret;
+// osmosdr::freq_range_t bandwidths = get_bandwidth_range( chan );
+
+ if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */
+ bandwidth = _sample_rate * 0.75; /* select narrower filters to prevent aliasing */
+
+ if ( _dev ) {
+ /* compute best default value depending on sample rate (auto filter) */
+ uint32_t bw = hackrf_compute_baseband_filter_bw( uint32_t(bandwidth) );
+ ret = hackrf_set_baseband_filter_bandwidth( _dev, bw );
+ if ( HACKRF_SUCCESS == ret ) {
+ _bandwidth = bw;
+ } else {
+ HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_baseband_filter_bandwidth", bw ) )
+ }
+ }
+
+ return _bandwidth;
}
double hackrf_source_c::get_bandwidth( size_t chan )
{
- return hackrf_common::get_bandwidth(chan);
+ return _bandwidth;
}
osmosdr::freq_range_t hackrf_source_c::get_bandwidth_range( size_t chan )
{
- return hackrf_common::get_bandwidth_range(chan);
+ osmosdr::freq_range_t bandwidths;
+
+ // TODO: read out from libhackrf when an API is available
+
+ bandwidths += osmosdr::range_t( 1750000 );
+ bandwidths += osmosdr::range_t( 2500000 );
+ bandwidths += osmosdr::range_t( 3500000 );
+ bandwidths += osmosdr::range_t( 5000000 );
+ bandwidths += osmosdr::range_t( 5500000 );
+ bandwidths += osmosdr::range_t( 6000000 );
+ bandwidths += osmosdr::range_t( 7000000 );
+ bandwidths += osmosdr::range_t( 8000000 );
+ bandwidths += osmosdr::range_t( 9000000 );
+ bandwidths += osmosdr::range_t( 10000000 );
+ bandwidths += osmosdr::range_t( 12000000 );
+ bandwidths += osmosdr::range_t( 14000000 );
+ bandwidths += osmosdr::range_t( 15000000 );
+ bandwidths += osmosdr::range_t( 20000000 );
+ bandwidths += osmosdr::range_t( 24000000 );
+ bandwidths += osmosdr::range_t( 28000000 );
+
+ return bandwidths;
}
diff --git a/lib/hackrf/hackrf_source_c.h b/lib/hackrf/hackrf_source_c.h
index 0d38ac0..6ae81d2 100644
--- a/lib/hackrf/hackrf_source_c.h
+++ b/lib/hackrf/hackrf_source_c.h
@@ -1,35 +1,36 @@
/* -*- c++ -*- */
/*
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
- * Copyright 2020 Clayton Smith <argilo@gmail.com>
*
- * gr-osmosdr is free software; you can redistribute it and/or modify
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
- * gr-osmosdr is distributed in the hope that it will be useful,
+ * GNU Radio 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with gr-osmosdr; see the file COPYING. If not, write to
+ * along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_HACKRF_SOURCE_C_H
#define INCLUDED_HACKRF_SOURCE_C_H
+#include <gnuradio/thread/thread.h>
#include <gnuradio/sync_block.h>
-#include <condition_variable>
-#include <mutex>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <libhackrf/hackrf.h>
#include "source_iface.h"
-#include "hackrf_common.h"
class hackrf_source_c;
@@ -61,12 +62,12 @@ hackrf_source_c_sptr make_hackrf_source_c (const std::string & args = "");
*/
class hackrf_source_c :
public gr::sync_block,
- public source_iface,
- protected hackrf_common
+ public source_iface
{
private:
// The friend declaration allows make_hackrf_source_c to
// access the private constructor.
+
friend hackrf_source_c_sptr make_hackrf_source_c (const std::string & args);
/*!
@@ -122,22 +123,35 @@ public:
private:
static int _hackrf_rx_callback(hackrf_transfer* transfer);
int hackrf_rx_callback(unsigned char *buf, uint32_t len);
+ static void _hackrf_wait(hackrf_source_c *obj);
+ void hackrf_wait();
+
+ static int _usage;
+ static boost::mutex _usage_mutex;
- std::vector<float> _lut;
+ std::vector<gr_complex> _lut;
- unsigned char **_buf;
+ hackrf_device *_dev;
+ gr::thread::thread _thread;
+ unsigned short **_buf;
unsigned int _buf_num;
unsigned int _buf_len;
unsigned int _buf_head;
unsigned int _buf_used;
- std::mutex _buf_mutex;
- std::condition_variable _buf_cond;
+ boost::mutex _buf_mutex;
+ boost::condition_variable _buf_cond;
unsigned int _buf_offset;
int _samp_avail;
+ double _sample_rate;
+ double _center_freq;
+ double _freq_corr;
+ bool _auto_gain;
+ double _amp_gain;
double _lna_gain;
double _vga_gain;
+ double _bandwidth;
};
#endif /* INCLUDED_HACKRF_SOURCE_C_H */
diff --git a/lib/xtrx/CMakeLists.txt b/lib/miri/CMakeLists.txt
index 9297bf0..ddaeb0a 100644
--- a/lib/xtrx/CMakeLists.txt
+++ b/lib/miri/CMakeLists.txt
@@ -21,15 +21,17 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
- ${LIBXTRX_INCLUDE_DIRS}
+ ${LIBMIRISDR_INCLUDE_DIRS}
)
-list(APPEND gr_osmosdr_srcs
- ${CMAKE_CURRENT_SOURCE_DIR}/xtrx_obj.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/xtrx_source_c.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/xtrx_sink_c.cc
+set(mirisdr_srcs
+ ${CMAKE_CURRENT_SOURCE_DIR}/miri_source_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+########################################################################
+# Append gnuradio-mirisdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${mirisdr_srcs})
+list(APPEND gr_osmosdr_libs ${LIBMIRISDR_LIBRARIES})
diff --git a/lib/miri/miri_source_c.cc b/lib/miri/miri_source_c.cc
new file mode 100644
index 0000000..c9f81fa
--- /dev/null
+++ b/lib/miri/miri_source_c.cc
@@ -0,0 +1,451 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ * Copyright 2012 Steve Markgraf <steve@steve-m.de>
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * config.h is generated by configure. It contains the results
+ * of probing for features, options etc. It should be the first
+ * file included in your .cc file.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "miri_source_c.h"
+#include <gnuradio/io_signature.h>
+
+#include <boost/assign.hpp>
+#include <boost/format.hpp>
+
+#include <stdexcept>
+#include <iostream>
+#include <stdio.h>
+
+#include <mirisdr.h>
+
+#include "arg_helpers.h"
+
+using namespace boost::assign;
+
+#define BUF_SIZE 2304 * 8 * 2
+#define BUF_NUM 15
+#define BUF_SKIP 1 // buffers to skip due to garbage
+
+#define BYTES_PER_SAMPLE 4 // mirisdr device delivers 16 bit signed IQ data
+ // containing 12 bits of information
+
+/*
+ * Create a new instance of miri_source_c and return
+ * a boost shared_ptr. This is effectively the public constructor.
+ */
+miri_source_c_sptr
+make_miri_source_c (const std::string &args)
+{
+ return gnuradio::get_initial_sptr(new miri_source_c (args));
+}
+
+/*
+ * Specify constraints on number of input and output streams.
+ * This info is used to construct the input and output signatures
+ * (2nd & 3rd args to gr::block's constructor). The input and
+ * output signatures are used by the runtime system to
+ * check that a valid number and type of inputs and outputs
+ * are connected to this block. In this case, we accept
+ * only 0 input and 1 output.
+ */
+static const int MIN_IN = 0; // mininum number of input streams
+static const int MAX_IN = 0; // maximum number of input streams
+static const int MIN_OUT = 1; // minimum number of output streams
+static const int MAX_OUT = 1; // maximum number of output streams
+
+/*
+ * The private constructor
+ */
+miri_source_c::miri_source_c (const std::string &args)
+ : gr::sync_block ("miri_source_c",
+ gr::io_signature::make(MIN_IN, MAX_IN, sizeof (gr_complex)),
+ gr::io_signature::make(MIN_OUT, MAX_OUT, sizeof (gr_complex))),
+ _running(true),
+ _auto_gain(false),
+ _skipped(0)
+{
+ int ret;
+ unsigned int dev_index = 0;
+
+ dict_t dict = params_to_dict(args);
+
+ if (dict.count("miri"))
+ dev_index = boost::lexical_cast< unsigned int >( dict["miri"] );
+
+ _buf_num = _buf_head = _buf_used = _buf_offset = 0;
+ _samp_avail = BUF_SIZE / BYTES_PER_SAMPLE;
+
+ if (dict.count("buffers"))
+ _buf_num = boost::lexical_cast< unsigned int >( dict["buffers"] );
+
+ if (0 == _buf_num)
+ _buf_num = BUF_NUM;
+
+ if ( BUF_NUM != _buf_num ) {
+ std::cerr << "Using " << _buf_num << " buffers of size " << BUF_SIZE << "."
+ << std::endl;
+ }
+
+ if ( dev_index >= mirisdr_get_device_count() )
+ throw std::runtime_error("Wrong mirisdr device index given.");
+
+ std::cerr << "Using device #" << dev_index << ": "
+ << mirisdr_get_device_name(dev_index)
+ << std::endl;
+
+ _dev = NULL;
+ ret = mirisdr_open( &_dev, dev_index );
+ if (ret < 0)
+ throw std::runtime_error("Failed to open mirisdr device.");
+#if 0
+ ret = mirisdr_set_sample_rate( _dev, 500000 );
+ if (ret < 0)
+ throw std::runtime_error("Failed to set default samplerate.");
+
+ ret = mirisdr_set_tuner_gain_mode(_dev, int(!_auto_gain));
+ if (ret < 0)
+ throw std::runtime_error("Failed to enable manual gain mode.");
+#endif
+ ret = mirisdr_reset_buffer( _dev );
+ if (ret < 0)
+ throw std::runtime_error("Failed to reset usb buffers.");
+
+ _buf = (unsigned short **) malloc(_buf_num * sizeof(unsigned short *));
+ _buf_lens = (unsigned int *) malloc(_buf_num * sizeof(unsigned int));
+
+ if (_buf && _buf_lens) {
+ for(unsigned int i = 0; i < _buf_num; ++i)
+ _buf[i] = (unsigned short *) malloc(BUF_SIZE);
+ }
+
+ _thread = gr::thread::thread(_mirisdr_wait, this);
+}
+
+/*
+ * Our virtual destructor.
+ */
+miri_source_c::~miri_source_c ()
+{
+ if (_dev) {
+ _running = false;
+ mirisdr_cancel_async( _dev );
+ _thread.join();
+ mirisdr_close( _dev );
+ _dev = NULL;
+ }
+
+ if (_buf) {
+ for(unsigned int i = 0; i < _buf_num; ++i) {
+ free(_buf[i]);
+ }
+
+ free(_buf);
+ _buf = NULL;
+ free(_buf_lens);
+ _buf_lens = NULL;
+ }
+}
+
+void miri_source_c::_mirisdr_callback(unsigned char *buf, uint32_t len, void *ctx)
+{
+ miri_source_c *obj = (miri_source_c *)ctx;
+ obj->mirisdr_callback(buf, len);
+}
+
+void miri_source_c::mirisdr_callback(unsigned char *buf, uint32_t len)
+{
+ if (_skipped < BUF_SKIP) {
+ _skipped++;
+ return;
+ }
+
+ {
+ boost::mutex::scoped_lock lock( _buf_mutex );
+
+ if (len > BUF_SIZE)
+ throw std::runtime_error("Buffer too small.");
+
+ int buf_tail = (_buf_head + _buf_used) % _buf_num;
+ memcpy(_buf[buf_tail], buf, len);
+ _buf_lens[buf_tail] = len;
+
+ if (_buf_used == _buf_num) {
+ std::cerr << "O" << std::flush;
+ _buf_head = (_buf_head + 1) % _buf_num;
+ } else {
+ _buf_used++;
+ }
+ }
+
+ _buf_cond.notify_one();
+}
+
+void miri_source_c::_mirisdr_wait(miri_source_c *obj)
+{
+ obj->mirisdr_wait();
+}
+
+void miri_source_c::mirisdr_wait()
+{
+ int ret = mirisdr_read_async( _dev, _mirisdr_callback, (void *)this, _buf_num, BUF_SIZE );
+
+ _running = false;
+
+ if ( ret != 0 )
+ std::cerr << "mirisdr_read_async returned with " << ret << std::endl;
+
+ _buf_cond.notify_one();
+}
+
+int miri_source_c::work( int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items )
+{
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ {
+ boost::mutex::scoped_lock lock( _buf_mutex );
+
+ while (_buf_used < 3 && _running) // collect at least 3 buffers
+ _buf_cond.wait( lock );
+ }
+
+ if (!_running)
+ return WORK_DONE;
+
+ short *buf = (short *)_buf[_buf_head] + _buf_offset;
+
+ if (noutput_items <= _samp_avail) {
+ for (int i = 0; i < noutput_items; i++)
+ *out++ = gr_complex( float(*(buf + i * 2 + 0)) * (1.0f/4096.0f),
+ float(*(buf + i * 2 + 1)) * (1.0f/4096.0f) );
+
+ _buf_offset += noutput_items * 2;
+ _samp_avail -= noutput_items;
+ } else {
+ for (int i = 0; i < _samp_avail; i++)
+ *out++ = gr_complex( float(*(buf + i * 2 + 0)) * (1.0f/4096.0f),
+ float(*(buf + i * 2 + 1)) * (1.0f/4096.0f) );
+
+ {
+ boost::mutex::scoped_lock lock( _buf_mutex );
+
+ _buf_head = (_buf_head + 1) % _buf_num;
+ _buf_used--;
+ }
+
+ buf = (short *)_buf[_buf_head];
+
+ int remaining = noutput_items - _samp_avail;
+
+ for (int i = 0; i < remaining; i++)
+ *out++ = gr_complex( float(*(buf + i * 2 + 0)) * (1.0f/4096.0f),
+ float(*(buf + i * 2 + 1)) * (1.0f/4096.0f) );
+
+ _buf_offset = remaining * 2;
+ _samp_avail = (_buf_lens[_buf_head] / BYTES_PER_SAMPLE) - remaining;
+ }
+
+ return noutput_items;
+}
+
+std::vector<std::string> miri_source_c::get_devices()
+{
+ std::vector<std::string> devices;
+
+ for (unsigned int i = 0; i < mirisdr_get_device_count(); i++) {
+ std::string args = "miri=" + boost::lexical_cast< std::string >( i );
+ args += ",label='" + std::string(mirisdr_get_device_name( i )) + "'";
+ devices.push_back( args );
+ }
+
+ return devices;
+}
+
+size_t miri_source_c::get_num_channels()
+{
+ return 1;
+}
+
+osmosdr::meta_range_t miri_source_c::get_sample_rates()
+{
+ osmosdr::meta_range_t range;
+
+ range += osmosdr::range_t( 8000000 ); // known to work
+
+ return range;
+}
+
+double miri_source_c::set_sample_rate(double rate)
+{
+ if (_dev) {
+ mirisdr_set_sample_rate( _dev, (uint32_t)rate );
+ }
+
+ return get_sample_rate();
+}
+
+double miri_source_c::get_sample_rate()
+{
+ if (_dev)
+ return (double)mirisdr_get_sample_rate( _dev );
+
+ return 0;
+}
+
+osmosdr::freq_range_t miri_source_c::get_freq_range( size_t chan )
+{
+ osmosdr::freq_range_t range;
+
+ range += osmosdr::range_t( 150e3, 30e6 ); /* LW/MW/SW (150 kHz - 30 MHz) */
+ range += osmosdr::range_t( 64e6, 108e6 ); /* VHF Band II (64 - 108 MHz) */
+ range += osmosdr::range_t( 162e6, 240e6 ); /* Band III (162 - 240 MHz) */
+ range += osmosdr::range_t( 470e6, 960e6 ); /* Band IV/V (470 - 960 MHz) */
+ range += osmosdr::range_t( 1450e6, 1675e6 ); /* L-Band (1450 - 1675 MHz) */
+
+ return range;
+}
+
+double miri_source_c::set_center_freq( double freq, size_t chan )
+{
+ if (_dev)
+ mirisdr_set_center_freq( _dev, (uint32_t)freq );
+
+ return get_center_freq( chan );
+}
+
+double miri_source_c::get_center_freq( size_t chan )
+{
+ if (_dev)
+ return (double)mirisdr_get_center_freq( _dev );
+
+ return 0;
+}
+
+double miri_source_c::set_freq_corr( double ppm, size_t chan )
+{
+ return get_freq_corr( chan );
+}
+
+double miri_source_c::get_freq_corr( size_t chan )
+{
+ return 0;
+}
+
+std::vector<std::string> miri_source_c::get_gain_names( size_t chan )
+{
+ std::vector< std::string > gains;
+
+ gains += "LNA";
+
+ return gains;
+}
+
+osmosdr::gain_range_t miri_source_c::get_gain_range( size_t chan )
+{
+ osmosdr::gain_range_t range;
+
+ if (_dev) {
+ int count = mirisdr_get_tuner_gains(_dev, NULL);
+ if (count > 0) {
+ int* gains = new int[ count ];
+ count = mirisdr_get_tuner_gains(_dev, gains);
+ for (int i = 0; i < count; i++)
+ range += osmosdr::range_t( gains[i] / 10.0 );
+ delete[] gains;
+ }
+ }
+
+ return range;
+}
+
+osmosdr::gain_range_t miri_source_c::get_gain_range( const std::string & name, size_t chan )
+{
+ return get_gain_range( chan );
+}
+
+bool miri_source_c::set_gain_mode( bool automatic, size_t chan )
+{
+ if (_dev) {
+ if (!mirisdr_set_tuner_gain_mode(_dev, int(!automatic))) {
+ _auto_gain = automatic;
+ }
+ }
+
+ return get_gain_mode(chan);
+}
+
+bool miri_source_c::get_gain_mode( size_t chan )
+{
+ return _auto_gain;
+}
+
+double miri_source_c::set_gain( double gain, size_t chan )
+{
+ osmosdr::gain_range_t rf_gains = miri_source_c::get_gain_range( chan );
+
+ if (_dev) {
+ mirisdr_set_tuner_gain( _dev, int(rf_gains.clip(gain) * 10.0) );
+ }
+
+ return get_gain( chan );
+}
+
+double miri_source_c::set_gain( double gain, const std::string & name, size_t chan)
+{
+ return set_gain( gain, chan );
+}
+
+double miri_source_c::get_gain( size_t chan )
+{
+ if ( _dev )
+ return ((double)mirisdr_get_tuner_gain( _dev )) / 10.0;
+
+ return 0;
+}
+
+double miri_source_c::get_gain( const std::string & name, size_t chan )
+{
+ return get_gain( chan );
+}
+
+std::vector< std::string > miri_source_c::get_antennas( size_t chan )
+{
+ std::vector< std::string > antennas;
+
+ antennas += get_antenna( chan );
+
+ return antennas;
+}
+
+std::string miri_source_c::set_antenna( const std::string & antenna, size_t chan )
+{
+ return get_antenna( chan );
+}
+
+std::string miri_source_c::get_antenna( size_t chan )
+{
+ return "RX";
+}
diff --git a/lib/airspyhf/airspyhf_source_c.h b/lib/miri/miri_source_c.h
index dbdd87a..5363db5 100644
--- a/lib/airspyhf/airspyhf_source_c.h
+++ b/lib/miri/miri_source_c.h
@@ -1,8 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
- *
- * This file is part of GNU Radio
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,54 +17,63 @@
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
-#ifndef INCLUDED_AIRSPYHF_SOURCE_C_H
-#define INCLUDED_AIRSPYHF_SOURCE_C_H
-
-#include <boost/circular_buffer.hpp>
-
-#include <mutex>
-#include <condition_variable>
+#ifndef INCLUDED_MIRI_SOURCE_C_H
+#define INCLUDED_MIRI_SOURCE_C_H
#include <gnuradio/sync_block.h>
-#include <libairspyhf/airspyhf.h>
+#include <gnuradio/thread/thread.h>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include "source_iface.h"
-class airspyhf_source_c;
+class miri_source_c;
+typedef struct mirisdr_dev mirisdr_dev_t;
-typedef boost::shared_ptr<airspyhf_source_c> airspyhf_source_c_sptr;
+/*
+ * We use boost::shared_ptr's instead of raw pointers for all access
+ * to gr::blocks (and many other data structures). The shared_ptr gets
+ * us transparent reference counting, which greatly simplifies storage
+ * management issues. This is especially helpful in our hybrid
+ * C++ / Python system.
+ *
+ * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
+ *
+ * As a convention, the _sptr suffix indicates a boost::shared_ptr
+ */
+typedef boost::shared_ptr<miri_source_c> miri_source_c_sptr;
/*!
- * \brief Return a shared_ptr to a new instance of airspyhf_source_c.
+ * \brief Return a shared_ptr to a new instance of miri_source_c.
*
- * To avoid accidental use of raw pointers, airspyhf_source_c's
- * constructor is private. make_airspyhf_source_c is the public
+ * To avoid accidental use of raw pointers, miri_source_c's
+ * constructor is private. make_miri_source_c is the public
* interface for creating new instances.
*/
-airspyhf_source_c_sptr make_airspyhf_source_c (const std::string & args = "");
+miri_source_c_sptr make_miri_source_c (const std::string & args = "");
/*!
* \brief Provides a stream of complex samples.
* \ingroup block
*/
-class airspyhf_source_c :
+class miri_source_c :
public gr::sync_block,
public source_iface
{
private:
- // The friend declaration allows make_airspyhf_source_c to
+ // The friend declaration allows make_miri_source_c to
// access the private constructor.
- friend airspyhf_source_c_sptr make_airspyhf_source_c (const std::string & args);
-
- airspyhf_source_c (const std::string & args);
+ friend miri_source_c_sptr make_miri_source_c (const std::string & args);
-public:
- ~airspyhf_source_c ();
+ /*!
+ * \brief Provides a stream of complex samples.
+ */
+ miri_source_c (const std::string & args); // private constructor
- bool start();
- bool stop();
+ public:
+ ~miri_source_c (); // public destructor
int work( int noutput_items,
gr_vector_const_void_star &input_items,
@@ -89,6 +96,8 @@ public:
std::vector<std::string> get_gain_names( size_t chan = 0 );
osmosdr::gain_range_t get_gain_range( size_t chan = 0 );
osmosdr::gain_range_t get_gain_range( const std::string & name, size_t chan = 0 );
+ bool set_gain_mode( bool automatic, size_t chan = 0 );
+ bool get_gain_mode( size_t chan = 0 );
double set_gain( double gain, size_t chan = 0 );
double set_gain( double gain, const std::string & name, size_t chan = 0 );
double get_gain( size_t chan = 0 );
@@ -98,21 +107,28 @@ public:
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
std::string get_antenna( size_t chan = 0 );
-
private:
- static int _airspyhf_rx_callback(airspyhf_transfer_t* transfer);
- int airspyhf_rx_callback(void *samples, int sample_count);
-
- airspyhf_device *_dev;
-
- boost::circular_buffer<gr_complex> *_fifo;
- std::mutex _fifo_lock;
- std::condition_variable _samp_avail;
-
- std::vector< std::pair<double, uint32_t> > _sample_rates;
- double _sample_rate;
- double _center_freq;
- double _freq_corr;
+ static void _mirisdr_callback(unsigned char *buf, uint32_t len, void *ctx);
+ void mirisdr_callback(unsigned char *buf, uint32_t len);
+ static void _mirisdr_wait(miri_source_c *obj);
+ void mirisdr_wait();
+
+ mirisdr_dev_t *_dev;
+ gr::thread::thread _thread;
+ unsigned short **_buf;
+ unsigned int *_buf_lens;
+ unsigned int _buf_num;
+ unsigned int _buf_head;
+ unsigned int _buf_used;
+ boost::mutex _buf_mutex;
+ boost::condition_variable _buf_cond;
+ bool _running;
+
+ unsigned int _buf_offset;
+ int _samp_avail;
+
+ bool _auto_gain;
+ unsigned int _skipped;
};
-#endif /* INCLUDED_AIRSPY_SOURCE_C_H */
+#endif /* INCLUDED_MIRI_SOURCE_C_H */
diff --git a/lib/airspyhf/CMakeLists.txt b/lib/osmosdr/CMakeLists.txt
index fc13ce2..b0872f8 100644
--- a/lib/airspyhf/CMakeLists.txt
+++ b/lib/osmosdr/CMakeLists.txt
@@ -1,19 +1,19 @@
-# Copyright 2017 Free Software Foundation, Inc.
+# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,17 +21,17 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
- ${LIBAIRSPYHF_INCLUDE_DIRS}
+ ${LIBOSMOSDR_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- ${Gnuradio-blocks_LIBRARIES}
- ${LIBAIRSPYHF_LIBRARIES}
+set(osmosdr_srcs
+ ${CMAKE_CURRENT_SOURCE_DIR}/osmosdr_src_c.cc
)
-list(APPEND gr_osmosdr_srcs
- ${CMAKE_CURRENT_SOURCE_DIR}/airspyhf_source_c.cc
-)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${osmosdr_srcs})
+list(APPEND gr_osmosdr_libs ${LIBOSMOSDR_LIBRARIES})
diff --git a/lib/osmosdr/osmosdr_src_c.cc b/lib/osmosdr/osmosdr_src_c.cc
new file mode 100644
index 0000000..de65373
--- /dev/null
+++ b/lib/osmosdr/osmosdr_src_c.cc
@@ -0,0 +1,533 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * config.h is generated by configure. It contains the results
+ * of probing for features, options etc. It should be the first
+ * file included in your .cc file.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "osmosdr_src_c.h"
+#include <gnuradio/io_signature.h>
+
+#include <boost/assign.hpp>
+#include <boost/format.hpp>
+
+#include <stdexcept>
+#include <iostream>
+#include <stdio.h>
+
+#include <osmosdr.h>
+
+#include "arg_helpers.h"
+
+using namespace boost::assign;
+
+#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
+#define BUF_NUM 15
+#define BUF_SKIP 1 // buffers to skip due to garbage
+
+#define BYTES_PER_SAMPLE 4 // osmosdr device delivers 16 bit signed IQ data
+
+/*
+ * Create a new instance of osmosdr_src_c and return
+ * a boost shared_ptr. This is effectively the public constructor.
+ */
+osmosdr_src_c_sptr
+osmosdr_make_src_c (const std::string &args)
+{
+ return gnuradio::get_initial_sptr(new osmosdr_src_c (args));
+}
+
+/*
+ * The private constructor
+ */
+osmosdr_src_c::osmosdr_src_c (const std::string &args)
+ : gr::sync_block ("osmosdr_src_c",
+ gr::io_signature::make(0, 0, sizeof (gr_complex)),
+ gr::io_signature::make(1, 1, sizeof (gr_complex)) ),
+ _dev(NULL),
+ _buf(NULL),
+ _running(true),
+ _auto_gain(false),
+ _if_gain(0),
+ _skipped(0)
+{
+ int ret;
+ unsigned int dev_index = 0;
+
+ dict_t dict = params_to_dict(args);
+
+ if (dict.count("osmosdr"))
+ dev_index = boost::lexical_cast< unsigned int >( dict["osmosdr"] );
+
+ _buf_num = _buf_len = _buf_head = _buf_used = _buf_offset = 0;
+
+ if (dict.count("buffers"))
+ _buf_num = boost::lexical_cast< unsigned int >( dict["buffers"] );
+
+ if (dict.count("buflen"))
+ _buf_len = boost::lexical_cast< unsigned int >( dict["buflen"] );
+
+ if (0 == _buf_num)
+ _buf_num = BUF_NUM;
+
+ if (0 == _buf_len || _buf_len % 512 != 0) /* len must be multiple of 512 */
+ _buf_len = BUF_LEN;
+
+ if ( BUF_NUM != _buf_num || BUF_LEN != _buf_len ) {
+ std::cerr << "Using " << _buf_num << " buffers of size " << _buf_len << "."
+ << std::endl;
+ }
+
+ _samp_avail = _buf_len / BYTES_PER_SAMPLE;
+
+ if ( dev_index >= osmosdr_get_device_count() )
+ throw std::runtime_error("Wrong osmosdr device index given.");
+
+ std::cerr << "Using device #" << dev_index << ": "
+ << osmosdr_get_device_name(dev_index)
+ << std::endl;
+
+ _dev = NULL;
+ ret = osmosdr_open( &_dev, dev_index );
+ if (ret < 0)
+ throw std::runtime_error("Failed to open osmosdr device.");
+
+ ret = osmosdr_set_fpga_iq_swap(_dev, 0);
+ if (ret < 0)
+ throw std::runtime_error("Failed to disable IQ swapping.");
+
+ ret = osmosdr_set_sample_rate( _dev, 500000 );
+ if (ret < 0)
+ throw std::runtime_error("Failed to set default samplerate.");
+
+ ret = osmosdr_set_tuner_gain_mode(_dev, int(!_auto_gain));
+ if (ret < 0)
+ throw std::runtime_error("Failed to enable manual gain mode.");
+
+ ret = osmosdr_reset_buffer( _dev );
+ if (ret < 0)
+ throw std::runtime_error("Failed to reset usb buffers.");
+
+ set_if_gain( 24 ); /* preset to a reasonable default (non-GRC use case) */
+
+ _buf = (unsigned short **) malloc(_buf_num * sizeof(unsigned short *));
+
+ if (_buf) {
+ for(unsigned int i = 0; i < _buf_num; ++i)
+ _buf[i] = (unsigned short *) malloc(_buf_len);
+ }
+
+ _thread = gr::thread::thread(_osmosdr_wait, this);
+}
+
+/*
+ * Our virtual destructor.
+ */
+osmosdr_src_c::~osmosdr_src_c ()
+{
+ if (_dev) {
+ _running = false;
+ osmosdr_cancel_async( _dev );
+ _thread.join();
+ osmosdr_close( _dev );
+ _dev = NULL;
+ }
+
+ if (_buf) {
+ for(unsigned int i = 0; i < _buf_num; ++i) {
+ free(_buf[i]);
+ }
+
+ free(_buf);
+ _buf = NULL;
+ }
+}
+
+void osmosdr_src_c::_osmosdr_callback(unsigned char *buf, uint32_t len, void *ctx)
+{
+ osmosdr_src_c *obj = (osmosdr_src_c *)ctx;
+ obj->osmosdr_callback(buf, len);
+}
+
+void osmosdr_src_c::osmosdr_callback(unsigned char *buf, uint32_t len)
+{
+ if (_skipped < BUF_SKIP) {
+ _skipped++;
+ return;
+ }
+
+ {
+ boost::mutex::scoped_lock lock( _buf_mutex );
+
+ int buf_tail = (_buf_head + _buf_used) % _buf_num;
+ memcpy(_buf[buf_tail], buf, len);
+
+ if (_buf_used == _buf_num) {
+ std::cerr << "O" << std::flush;
+ _buf_head = (_buf_head + 1) % _buf_num;
+ } else {
+ _buf_used++;
+ }
+ }
+
+ _buf_cond.notify_one();
+}
+
+void osmosdr_src_c::_osmosdr_wait(osmosdr_src_c *obj)
+{
+ obj->osmosdr_wait();
+}
+
+void osmosdr_src_c::osmosdr_wait()
+{
+ int ret = osmosdr_read_async( _dev, _osmosdr_callback, (void *)this, _buf_num, _buf_len );
+
+ _running = false;
+
+ if ( ret != 0 )
+ std::cerr << "osmosdr_read_async returned with " << ret << std::endl;
+
+ _buf_cond.notify_one();
+}
+
+int osmosdr_src_c::work( int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items )
+{
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ {
+ boost::mutex::scoped_lock lock( _buf_mutex );
+
+ while (_buf_used < 3 && _running) // collect at least 3 buffers
+ _buf_cond.wait( lock );
+ }
+
+ if (!_running)
+ return WORK_DONE;
+
+ short *buf = (short *)_buf[_buf_head] + _buf_offset;
+
+ if (noutput_items <= _samp_avail) {
+ for (int i = 0; i < noutput_items; i++)
+ *out++ = gr_complex( float(*(buf + i * 2 + 0)) * (1.0f/32767.5f),
+ float(*(buf + i * 2 + 1)) * (1.0f/32767.5f) );
+
+ _buf_offset += noutput_items * 2;
+ _samp_avail -= noutput_items;
+ } else {
+ for (int i = 0; i < _samp_avail; i++)
+ *out++ = gr_complex( float(*(buf + i * 2 + 0)) * (1.0f/32767.5f),
+ float(*(buf + i * 2 + 1)) * (1.0f/32767.5f) );
+
+ {
+ boost::mutex::scoped_lock lock( _buf_mutex );
+
+ _buf_head = (_buf_head + 1) % _buf_num;
+ _buf_used--;
+ }
+
+ buf = (short *)_buf[_buf_head];
+
+ int remaining = noutput_items - _samp_avail;
+
+ for (int i = 0; i < remaining; i++)
+ *out++ = gr_complex( float(*(buf + i * 2 + 0)) * (1.0f/32767.5f),
+ float(*(buf + i * 2 + 1)) * (1.0f/32767.5f) );
+
+ _buf_offset = remaining * 2;
+ _samp_avail = (_buf_len / BYTES_PER_SAMPLE) - remaining;
+ }
+
+ return noutput_items;
+}
+
+std::vector<std::string> osmosdr_src_c::get_devices()
+{
+ std::vector< std::string > devices;
+ char buffer[256];
+
+ for (unsigned int i = 0; i < osmosdr_get_device_count(); i++) {
+ std::string args = "osmosdr=" + boost::lexical_cast< std::string >( i );
+
+ std::string label = std::string(osmosdr_get_device_name( i ));
+
+ memset(buffer, 0, sizeof(buffer));
+ osmosdr_get_device_usb_strings( i, NULL, NULL, buffer );
+ std::string serial = std::string(buffer);
+
+ if (serial.length())
+ label += " " + serial;
+
+ args += ",label='" + label + + "'";
+
+ devices.push_back( args );
+ }
+
+ return devices;
+}
+
+size_t osmosdr_src_c::get_num_channels()
+{
+ return 1;
+}
+
+osmosdr::meta_range_t osmosdr_src_c::get_sample_rates()
+{
+ osmosdr::meta_range_t range;
+
+ if (_dev) {
+ int count = osmosdr_get_sample_rates(_dev, NULL);
+ if (count > 0) {
+ uint32_t* rates = new uint32_t[ count ];
+ count = osmosdr_get_sample_rates(_dev, rates);
+ for (int i = 0; i < count; i++)
+ range += osmosdr::range_t( rates[i] );
+ delete[] rates;
+ }
+ }
+
+ return range;
+}
+
+double osmosdr_src_c::set_sample_rate(double rate)
+{
+ if (_dev) {
+ osmosdr_set_sample_rate( _dev, (uint32_t)rate );
+ }
+
+ return get_sample_rate();
+}
+
+double osmosdr_src_c::get_sample_rate()
+{
+ if (_dev)
+ return (double)osmosdr_get_sample_rate( _dev );
+
+ return 0;
+}
+
+osmosdr::freq_range_t osmosdr_src_c::get_freq_range( size_t chan )
+{
+ osmosdr::freq_range_t range;
+
+ /* there is a (temperature dependent) gap between 1100 to 1250 MHz */
+ range += osmosdr::range_t( 52e6, 2.2e9 );
+
+ return range;
+}
+
+double osmosdr_src_c::set_center_freq( double freq, size_t chan )
+{
+ if (_dev)
+ osmosdr_set_center_freq( _dev, (uint32_t)freq );
+
+ return get_center_freq( chan );
+}
+
+double osmosdr_src_c::get_center_freq( size_t chan )
+{
+ if (_dev)
+ return (double)osmosdr_get_center_freq( _dev );
+
+ return 0;
+}
+
+double osmosdr_src_c::set_freq_corr( double ppm, size_t chan )
+{
+ return get_freq_corr( chan );
+}
+
+double osmosdr_src_c::get_freq_corr( size_t chan )
+{
+ return 0;
+}
+
+std::vector<std::string> osmosdr_src_c::get_gain_names( size_t chan )
+{
+ std::vector< std::string > names;
+
+ names += "LNA";
+ names += "IF";
+
+ return names;
+}
+
+osmosdr::gain_range_t osmosdr_src_c::get_gain_range( size_t chan )
+{
+ osmosdr::gain_range_t range;
+
+ if (_dev) {
+ int count = osmosdr_get_tuner_gains(_dev, NULL);
+ if (count > 0) {
+ int* gains = new int[ count ];
+ count = osmosdr_get_tuner_gains(_dev, gains);
+ for (int i = 0; i < count; i++)
+ range += osmosdr::range_t( gains[i] / 10.0 );
+ delete[] gains;
+ }
+ }
+
+ return range;
+}
+
+osmosdr::gain_range_t osmosdr_src_c::get_gain_range( const std::string & name, size_t chan )
+{
+ if ( "IF" == name ) {
+ return osmosdr::gain_range_t(3, 56, 1);
+ }
+
+ return get_gain_range( chan );
+}
+
+bool osmosdr_src_c::set_gain_mode( bool automatic, size_t chan )
+{
+ if (_dev) {
+ if (!osmosdr_set_tuner_gain_mode(_dev, int(!automatic))) {
+ _auto_gain = automatic;
+ }
+ }
+
+ return get_gain_mode(chan);
+}
+
+bool osmosdr_src_c::get_gain_mode( size_t chan )
+{
+ return _auto_gain;
+}
+
+double osmosdr_src_c::set_gain( double gain, size_t chan )
+{
+ osmosdr::gain_range_t rf_gains = osmosdr_src_c::get_gain_range( chan );
+
+ if (_dev) {
+ osmosdr_set_tuner_gain( _dev, int(rf_gains.clip(gain) * 10.0) );
+ }
+
+ return get_gain( chan );
+}
+
+double osmosdr_src_c::set_gain( double gain, const std::string & name, size_t chan)
+{
+ if ( "IF" == name ) {
+ return set_if_gain( gain, chan );
+ }
+
+ return set_gain( gain, chan );
+}
+
+double osmosdr_src_c::get_gain( size_t chan )
+{
+ if ( _dev )
+ return ((double)osmosdr_get_tuner_gain( _dev )) / 10.0;
+
+ return 0;
+}
+
+double osmosdr_src_c::get_gain( const std::string & name, size_t chan )
+{
+ if ( "IF" == name ) {
+ return _if_gain;
+ }
+
+ return get_gain( chan );
+}
+
+double osmosdr_src_c::set_if_gain(double gain, size_t chan)
+{
+ std::vector< osmosdr::gain_range_t > if_gains;
+
+ if_gains += osmosdr::gain_range_t(-3, 6, 9);
+ if_gains += osmosdr::gain_range_t(0, 9, 3);
+ if_gains += osmosdr::gain_range_t(0, 9, 3);
+ if_gains += osmosdr::gain_range_t(0, 2, 1);
+ if_gains += osmosdr::gain_range_t(3, 15, 3);
+ if_gains += osmosdr::gain_range_t(3, 15, 3);
+
+ std::map< int, double > gains;
+
+ /* initialize with min gains */
+ for (unsigned int i = 0; i < if_gains.size(); i++) {
+ gains[ i + 1 ] = if_gains[ i ].start();
+ }
+
+ for (int i = if_gains.size() - 1; i >= 0; i--) {
+ osmosdr::gain_range_t range = if_gains[ i ];
+
+ double error = gain;
+
+ for( double g = range.start(); g <= range.stop(); g += range.step() ) {
+
+ double sum = 0;
+ for (int j = 0; j < int(gains.size()); j++) {
+ if ( i == j )
+ sum += g;
+ else
+ sum += gains[ j + 1 ];
+ }
+
+ double err = abs(gain - sum);
+ if (err < error) {
+ error = err;
+ gains[ i + 1 ] = g;
+ }
+ }
+ }
+#if 0
+ std::cerr << gain << " => "; double sum = 0;
+ for (unsigned int i = 0; i < gains.size(); i++) {
+ sum += gains[ i + 1 ];
+ std::cerr << gains[ i + 1 ] << " ";
+ }
+ std::cerr << " = " << sum << std::endl;
+#endif
+ if (_dev) {
+ for (unsigned int stage = 1; stage <= gains.size(); stage++) {
+ osmosdr_set_tuner_if_gain( _dev, stage, int(gains[ stage ] * 10.0));
+ }
+ }
+
+ _if_gain = gain;
+ return gain;
+}
+
+std::vector< std::string > osmosdr_src_c::get_antennas( size_t chan )
+{
+ std::vector< std::string > antennas;
+
+ antennas += get_antenna( chan );
+
+ return antennas;
+}
+
+std::string osmosdr_src_c::set_antenna( const std::string & antenna, size_t chan )
+{
+ return get_antenna( chan );
+}
+
+std::string osmosdr_src_c::get_antenna( size_t chan )
+{
+ return "RX";
+}
diff --git a/lib/osmosdr/osmosdr_src_c.h b/lib/osmosdr/osmosdr_src_c.h
new file mode 100644
index 0000000..0f62b09
--- /dev/null
+++ b/lib/osmosdr/osmosdr_src_c.h
@@ -0,0 +1,139 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_OSMOSDR_SRC_C_H
+#define INCLUDED_OSMOSDR_SRC_C_H
+
+#include <gnuradio/sync_block.h>
+
+#include <gnuradio/thread/thread.h>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+
+#include "source_iface.h"
+
+class osmosdr_src_c;
+typedef struct osmosdr_dev osmosdr_dev_t;
+
+/*
+ * We use boost::shared_ptr's instead of raw pointers for all access
+ * to gr::blocks (and many other data structures). The shared_ptr gets
+ * us transparent reference counting, which greatly simplifies storage
+ * management issues. This is especially helpful in our hybrid
+ * C++ / Python system.
+ *
+ * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
+ *
+ * As a convention, the _sptr suffix indicates a boost::shared_ptr
+ */
+typedef boost::shared_ptr<osmosdr_src_c> osmosdr_src_c_sptr;
+
+/*!
+ * \brief Return a shared_ptr to a new instance of osmosdr_src_c.
+ *
+ * To avoid accidental use of raw pointers, osmosdr_src_c's
+ * constructor is private. osmosdr_make_src_c is the public
+ * interface for creating new instances.
+ */
+osmosdr_src_c_sptr osmosdr_make_src_c (const std::string & args = "");
+
+/*!
+ * \brief Provides a stream of complex samples.
+ * \ingroup block
+ *
+ * \sa sink for a version that subclasses gr::hier_block2.
+ */
+class osmosdr_src_c :
+ public gr::sync_block,
+ public source_iface
+{
+private:
+ // The friend declaration allows osmosdr_make_src_c to
+ // access the private constructor.
+
+ friend osmosdr_src_c_sptr osmosdr_make_src_c (const std::string & args);
+
+ /*!
+ * \brief Provides a stream of complex samples.
+ */
+ osmosdr_src_c (const std::string & args); // private constructor
+
+ public:
+ ~osmosdr_src_c (); // public destructor
+
+ int work( int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items );
+
+ static std::vector< std::string > get_devices();
+
+ size_t get_num_channels( void );
+
+ osmosdr::meta_range_t get_sample_rates( void );
+ double set_sample_rate( double rate );
+ double get_sample_rate( void );
+
+ osmosdr::freq_range_t get_freq_range( size_t chan = 0 );
+ double set_center_freq( double freq, size_t chan = 0 );
+ double get_center_freq( size_t chan = 0 );
+ double set_freq_corr( double ppm, size_t chan = 0 );
+ double get_freq_corr( size_t chan = 0 );
+
+ std::vector<std::string> get_gain_names( size_t chan = 0 );
+ osmosdr::gain_range_t get_gain_range( size_t chan = 0 );
+ osmosdr::gain_range_t get_gain_range( const std::string & name, size_t chan = 0 );
+ bool set_gain_mode( bool automatic, size_t chan = 0 );
+ bool get_gain_mode( size_t chan = 0 );
+ double set_gain( double gain, size_t chan = 0 );
+ double set_gain( double gain, const std::string & name, size_t chan = 0 );
+ double get_gain( size_t chan = 0 );
+ double get_gain( const std::string & name, size_t chan = 0 );
+
+ double set_if_gain( double gain, size_t chan = 0 );
+
+ std::vector< std::string > get_antennas( size_t chan = 0 );
+ std::string set_antenna( const std::string & antenna, size_t chan = 0 );
+ std::string get_antenna( size_t chan = 0 );
+
+private:
+ static void _osmosdr_callback(unsigned char *buf, uint32_t len, void *ctx);
+ void osmosdr_callback(unsigned char *buf, uint32_t len);
+ static void _osmosdr_wait(osmosdr_src_c *obj);
+ void osmosdr_wait();
+
+ osmosdr_dev_t *_dev;
+ gr::thread::thread _thread;
+ unsigned short **_buf;
+ unsigned int _buf_num;
+ unsigned int _buf_len;
+ unsigned int _buf_head;
+ unsigned int _buf_used;
+ boost::mutex _buf_mutex;
+ boost::condition_variable _buf_cond;
+ bool _running;
+
+ unsigned int _buf_offset;
+ int _samp_avail;
+
+ bool _auto_gain;
+ double _if_gain;
+ unsigned int _skipped;
+};
+
+#endif /* INCLUDED_OSMOSDR_SRC_C_H */
diff --git a/lib/ranges.cc b/lib/ranges.cc
index 09c1dae..cdff969 100644
--- a/lib/ranges.cc
+++ b/lib/ranges.cc
@@ -18,6 +18,7 @@
#include <osmosdr/ranges.h>
#include <stdexcept>
#include <boost/math/special_functions/round.hpp>
+#include <boost/foreach.hpp>
#include <algorithm>
#include <sstream>
@@ -101,7 +102,7 @@ meta_range_t::meta_range_t(
double meta_range_t::start(void) const{
check_meta_range_monotonic(*this);
double min_start = this->front().start();
- for (const range_t &r : (*this)){
+ BOOST_FOREACH(const range_t &r, (*this)){
min_start = std::min(min_start, r.start());
}
return min_start;
@@ -110,7 +111,7 @@ double meta_range_t::start(void) const{
double meta_range_t::stop(void) const{
check_meta_range_monotonic(*this);
double max_stop = this->front().stop();
- for (const range_t &r : (*this)){
+ BOOST_FOREACH(const range_t &r, (*this)){
max_stop = std::max(max_stop, r.stop());
}
return max_stop;
@@ -120,7 +121,7 @@ double meta_range_t::step(void) const{
check_meta_range_monotonic(*this);
std::vector<double> non_zero_steps;
range_t last = this->front();
- for (const range_t &r : (*this)){
+ BOOST_FOREACH(const range_t &r, (*this)){
//steps at each range
if (r.step() > 0) non_zero_steps.push_back(r.step());
//and steps in-between ranges
@@ -136,7 +137,7 @@ double meta_range_t::step(void) const{
double meta_range_t::clip(double value, bool clip_step) const{
check_meta_range_monotonic(*this);
double last_stop = this->front().stop();
- for (const range_t &r : (*this)){
+ BOOST_FOREACH(const range_t &r, (*this)){
//in-between ranges, clip to nearest
if (value < r.start()){
return (std::abs(value - r.start()) < std::abs(value - last_stop))?
@@ -156,7 +157,7 @@ double meta_range_t::clip(double value, bool clip_step) const{
std::vector<double> meta_range_t::values() const {
std::vector<double> values;
- for (const range_t &r : (*this)) {
+ BOOST_FOREACH(const range_t &r, (*this)) {
if (r.start() != r.stop()) {
if ( r.step() == 0 ) {
values.push_back( r.start() );
@@ -176,7 +177,7 @@ std::vector<double> meta_range_t::values() const {
const std::string meta_range_t::to_pp_string(void) const{
std::stringstream ss;
- for (const range_t &r : (*this)){
+ BOOST_FOREACH(const range_t &r, (*this)){
ss << r.to_pp_string() << std::endl;
}
return ss.str();
diff --git a/lib/redpitaya/CMakeLists.txt b/lib/redpitaya/CMakeLists.txt
index 78f816b..a14dc9e 100644
--- a/lib/redpitaya/CMakeLists.txt
+++ b/lib/redpitaya/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,17 +21,18 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
-APPEND_LIB_LIST(
- ${Gnuradio-blocks_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(redpitaya_srcs
${CMAKE_CURRENT_SOURCE_DIR}/redpitaya_source_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/redpitaya_sink_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/redpitaya_common.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${redpitaya_srcs})
+#list(APPEND gr_osmosdr_libs ${GNURADIO_BLOCKS_LIBRARIES})
diff --git a/lib/rfspace/CMakeLists.txt b/lib/rfspace/CMakeLists.txt
index c096550..eebc15d 100644
--- a/lib/rfspace/CMakeLists.txt
+++ b/lib/rfspace/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,11 +21,17 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
-list(APPEND gr_osmosdr_srcs
+set(rfspace_srcs
${CMAKE_CURRENT_SOURCE_DIR}/rfspace_source_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${rfspace_srcs})
+#list(APPEND gr_osmosdr_libs ...)
+
diff --git a/lib/rfspace/rfspace_source_c.cc b/lib/rfspace/rfspace_source_c.cc
index 314dfc7..80f34df 100644
--- a/lib/rfspace/rfspace_source_c.cc
+++ b/lib/rfspace/rfspace_source_c.cc
@@ -27,6 +27,7 @@
#include "config.h"
#endif
+#ifndef USE_ASIO
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -34,6 +35,7 @@
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <netdb.h>
+#endif
#include <fcntl.h>
#include <unistd.h>
@@ -52,6 +54,9 @@
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
+#ifdef USE_ASIO
+#include <boost/asio/deadline_timer.hpp>
+#endif
#include <gnuradio/io_signature.h>
@@ -59,6 +64,9 @@
#include "rfspace_source_c.h"
using namespace boost::assign;
+#ifdef USE_ASIO
+using boost::asio::deadline_timer;
+#endif
#define DEFAULT_HOST "127.0.0.1" /* We assume a running "siqs" from CuteSDR project */
#define DEFAULT_PORT 50000
@@ -94,8 +102,15 @@ rfspace_source_c::rfspace_source_c (const std::string &args)
gr::io_signature::make (MIN_IN, MAX_IN, sizeof (gr_complex)),
gr::io_signature::make (MIN_OUT, MAX_OUT, sizeof (gr_complex))),
_radio(RADIO_UNKNOWN),
+#ifdef USE_ASIO
+ _io_service(),
+ _resolver(_io_service),
+ _t(_io_service),
+ _u(_io_service),
+#else
_tcp(-1),
_udp(-1),
+#endif
_usb(-1),
_running(false),
_keep_running(false),
@@ -224,6 +239,30 @@ rfspace_source_c::rfspace_source_c (const std::string &args)
/* SDR-IP 4.4.4 Data Output UDP IP and Port Address */
/* NETSDR 4.4.3 Data Output UDP IP and Port Address */
+#ifdef USE_ASIO
+
+ tcp::resolver::query query(tcp::v4(), host.c_str(), port_str.c_str());
+ tcp::resolver::iterator iterator = _resolver.resolve(query);
+
+ boost::system::error_code ec;
+
+ boost::asio::connect(_t, iterator, ec);
+ if ( ec )
+ throw std::runtime_error(ec.message() + " (" + host + ":" + port_str + ")");
+
+ _u.open(udp::v4(), ec);
+ if ( ec )
+ throw std::runtime_error(ec.message());
+
+ _u.bind(udp::endpoint(udp::v4(), DEFAULT_PORT), ec);
+ if ( ec )
+ throw std::runtime_error(ec.message());
+
+ _u.set_option(udp::socket::reuse_address(true));
+ _t.set_option(udp::socket::reuse_address(true));
+
+#else
+
if ( (_tcp = socket(AF_INET, SOCK_STREAM, 0) ) < 0)
{
throw std::runtime_error("Could not create TCP socket");
@@ -300,6 +339,8 @@ rfspace_source_c::rfspace_source_c (const std::string &args)
throw std::runtime_error("Bind of UDP socket failed: " + std::string(strerror(errno)));
}
+#endif
+
}
/* Wait 10 ms before sending queries to device (required for networked radios). */
@@ -465,8 +506,10 @@ rfspace_source_c::rfspace_source_c (const std::string &args)
*/
rfspace_source_c::~rfspace_source_c ()
{
+#ifndef USE_ASIO
close(_tcp);
close(_udp);
+#endif
if ( RFSPACE_SDR_IQ == _radio )
{
@@ -547,7 +590,7 @@ bool rfspace_source_c::transaction( const unsigned char *cmd, size_t size,
if ( write(_usb, cmd, size) != (int)size )
return false;
- std::unique_lock<std::mutex> lock(_resp_lock);
+ boost::unique_lock<boost::mutex> lock(_resp_lock);
_resp_avail.wait(lock);
rx_bytes = _resp.size();
@@ -555,8 +598,13 @@ bool rfspace_source_c::transaction( const unsigned char *cmd, size_t size,
}
else
{
- std::lock_guard<std::mutex> lock(_tcp_lock);
+ boost::mutex::scoped_lock lock(_tcp_lock);
+
+#ifdef USE_ASIO
+ _t.write_some( boost::asio::buffer(cmd, size) );
+ rx_bytes = _t.read_some( boost::asio::buffer(data, sizeof(data)) );
+#else
if ( write(_tcp, cmd, size) != (int)size )
return false;
@@ -576,6 +624,7 @@ bool rfspace_source_c::transaction( const unsigned char *cmd, size_t size,
return false;
rx_bytes = 2 + length; /* header + payload */
+#endif
}
response.resize( rx_bytes );
@@ -780,7 +829,7 @@ int rfspace_source_c::work( int noutput_items,
{
gr_complex *out = (gr_complex *)output_items[0];
- std::unique_lock<std::mutex> lock(_fifo_lock);
+ boost::unique_lock<boost::mutex> lock(_fifo_lock);
/* Wait until we have the requested number of samples */
int n_samples_avail = _fifo->size();
@@ -803,6 +852,10 @@ int rfspace_source_c::work( int noutput_items,
return noutput_items;
}
+#ifdef USE_ASIO
+ udp::endpoint ep;
+ size_t rx_bytes = _u.receive_from( boost::asio::buffer(data, sizeof(data)), ep );
+#else
struct sockaddr_in sa_in; /* remote address */
socklen_t addrlen = sizeof(sa_in); /* length of addresses */
ssize_t rx_bytes = recvfrom(_udp, data, sizeof(data), 0, (struct sockaddr *)&sa_in, &addrlen);
@@ -811,6 +864,7 @@ int rfspace_source_c::work( int noutput_items,
std::cerr << "recvfrom returned " << rx_bytes << std::endl;
return WORK_DONE;
}
+#endif
#define HEADER_SIZE 2
#define SEQNUM_SIZE 2
@@ -838,7 +892,11 @@ int rfspace_source_c::work( int noutput_items,
if ( diff > 1 )
{
std::cerr << "Lost " << diff << " packets from "
+#ifdef USE_ASIO
+ << ep
+#else
<< inet_ntoa(sa_in.sin_addr) << ":" << ntohs(sa_in.sin_port)
+#endif
<< std::endl;
}
@@ -919,11 +977,48 @@ typedef struct
uint16_t port;
} unit_t;
+#ifdef USE_ASIO
+static void handle_receive( const boost::system::error_code& ec,
+ std::size_t length,
+ boost::system::error_code* out_ec,
+ std::size_t* out_length )
+{
+ *out_ec = ec;
+ *out_length = length;
+}
+
+static void handle_timer( const boost::system::error_code& ec,
+ boost::system::error_code* out_ec )
+{
+ *out_ec = boost::asio::error::timed_out;
+}
+#endif
static std::vector < unit_t > discover_netsdr()
{
std::vector < unit_t > units;
+#ifdef USE_ASIO
+ boost::system::error_code ec;
+ boost::asio::io_service ios;
+ udp::socket socket(ios);
+ deadline_timer timer(ios);
+
+ timer.expires_at(boost::posix_time::pos_infin);
+
+ socket.open(udp::v4(), ec);
+
+ if ( ec )
+ return units;
+
+ socket.bind(udp::endpoint(udp::v4(), DISCOVER_CLIENT_PORT), ec);
+
+ if ( ec )
+ return units;
+
+ socket.set_option(udp::socket::reuse_address(true));
+ socket.set_option(boost::asio::socket_base::broadcast(true));
+#else
int sock;
if ( (sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
@@ -963,6 +1058,7 @@ static std::vector < unit_t > discover_netsdr()
close(sock);
return units;
}
+#endif
discover_common_msg_t tx_msg;
memset( (void *)&tx_msg, 0, sizeof(discover_common_msg_t) );
@@ -971,18 +1067,64 @@ static std::vector < unit_t > discover_netsdr()
tx_msg.key[0] = KEY0;
tx_msg.key[1] = KEY1;
tx_msg.op = MSG_REQ;
+#ifdef USE_ASIO
+ udp::endpoint ep(boost::asio::ip::address_v4::broadcast(), DISCOVER_SERVER_PORT);
+ socket.send_to(boost::asio::buffer(&tx_msg, sizeof(tx_msg)), ep);
+#else
sendto(sock, &tx_msg, sizeof(tx_msg), 0, (struct sockaddr *)&peer_sa, sizeof(peer_sa));
+#endif
while ( true )
{
std::size_t rx_bytes = 0;
unsigned char data[1024*2];
+#ifdef USE_ASIO
+ // Set up the variables that receive the result of the asynchronous
+ // operation. The error code is set to would_block to signal that the
+ // operation is incomplete. Asio guarantees that its asynchronous
+ // operations will never fail with would_block, so any other value in
+ // ec indicates completion.
+ ec = boost::asio::error::would_block;
+
+ // Start the asynchronous receive operation. The handle_receive function
+ // used as a callback will update the ec and rx_bytes variables.
+ socket.async_receive( boost::asio::buffer(data, sizeof(data)),
+ boost::bind(handle_receive, _1, _2, &ec, &rx_bytes) );
+
+ // Set a deadline for the asynchronous operation.
+ timer.expires_from_now( boost::posix_time::milliseconds(10) );
+
+ // Start an asynchronous wait on the timer. The handle_timer function
+ // used as a callback will update the ec variable.
+ timer.async_wait( boost::bind(handle_timer, _1, &ec) );
+
+ // Reset the io_service in preparation for a subsequent run_one() invocation.
+ ios.reset();
+
+ // Block until at least one asynchronous operation has completed.
+ do ios.run_one(); while ( ec == boost::asio::error::would_block );
+
+ if ( boost::asio::error::timed_out == ec ) /* timer was first to complete */
+ {
+ // Please note that cancel() has portability issues on some versions of
+ // Microsoft Windows, and it may be necessary to use close() instead.
+ // Consult the documentation for cancel() for further information.
+ socket.cancel();
+
+ break;
+ }
+ else /* socket was first to complete */
+ {
+ timer.cancel();
+ }
+#else
socklen_t addrlen = sizeof(peer_sa); /* length of addresses */
int nbytes = recvfrom(sock, data, sizeof(data), 0, (struct sockaddr *)&peer_sa, &addrlen);
if ( nbytes <= 0 )
break;
rx_bytes = nbytes;
+#endif
if ( rx_bytes >= sizeof(discover_common_msg_t) )
{
@@ -1009,7 +1151,11 @@ static std::vector < unit_t > discover_netsdr()
}
}
}
+#ifdef USE_ASIO
+ socket.close(ec);
+#else
close(sock);
+#endif
return units;
}
@@ -1150,7 +1296,7 @@ std::vector<std::string> rfspace_source_c::get_devices( bool fake )
std::vector < unit_t > units = discover_netsdr();
- for (unit_t u : units)
+ BOOST_FOREACH( unit_t u, units )
{
// std::cerr << u.name << " " << u.sn << " " << u.addr << ":" << u.port
// << std::endl;
@@ -1164,7 +1310,7 @@ std::vector<std::string> rfspace_source_c::get_devices( bool fake )
units = discover_sdr_iq();
- for (unit_t u : units)
+ BOOST_FOREACH( unit_t u, units )
{
// std::cerr << u.name << " " << u.sn << " " << u.addr << ":" << u.port
// << std::endl;
diff --git a/lib/rfspace/rfspace_source_c.h b/lib/rfspace/rfspace_source_c.h
index d2bf66d..c656063 100644
--- a/lib/rfspace/rfspace_source_c.h
+++ b/lib/rfspace/rfspace_source_c.h
@@ -20,17 +20,25 @@
#ifndef INCLUDED_RFSPACE_SOURCE_C_H
#define INCLUDED_RFSPACE_SOURCE_C_H
+//#define USE_ASIO
+
+#ifdef USE_ASIO
+#include <boost/asio.hpp>
+#endif
#include <gnuradio/thread/thread.h>
#include <gnuradio/block.h>
#include <gnuradio/sync_block.h>
#include <boost/circular_buffer.hpp>
-
-#include <mutex>
-#include <condition_variable>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include "osmosdr/ranges.h"
#include "source_iface.h"
+#ifdef USE_ASIO
+using boost::asio::ip::tcp;
+using boost::asio::ip::udp;
+#endif
class rfspace_source_c;
#ifndef SOCKET
@@ -135,8 +143,15 @@ private: /* members */
radio_type _radio;
+#ifdef USE_ASIO
+ boost::asio::io_service _io_service;
+ tcp::resolver _resolver;
+ tcp::socket _t;
+ udp::socket _u;
+#else
SOCKET _tcp;
SOCKET _udp;
+#endif
int _usb;
bool _running;
bool _keep_running;
@@ -149,15 +164,15 @@ private: /* members */
gr::thread::thread _thread;
bool _run_usb_read_task;
bool _run_tcp_keepalive_task;
- std::mutex _tcp_lock;
+ boost::mutex _tcp_lock;
boost::circular_buffer<gr_complex> *_fifo;
- std::mutex _fifo_lock;
- std::condition_variable _samp_avail;
+ boost::mutex _fifo_lock;
+ boost::condition_variable _samp_avail;
std::vector< unsigned char > _resp;
- std::mutex _resp_lock;
- std::condition_variable _resp_avail;
+ boost::mutex _resp_lock;
+ boost::condition_variable _resp_avail;
};
#endif /* INCLUDED_RFSPACE_SOURCE_C_H */
diff --git a/lib/rtl/CMakeLists.txt b/lib/rtl/CMakeLists.txt
index 443f3c0..f438df5 100644
--- a/lib/rtl/CMakeLists.txt
+++ b/lib/rtl/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,16 +21,18 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${LIBRTLSDR_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- ${LIBRTLSDR_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(rtl_srcs
${CMAKE_CURRENT_SOURCE_DIR}/rtl_source_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${rtl_srcs})
+list(APPEND gr_osmosdr_libs ${LIBRTLSDR_LIBRARIES})
+
diff --git a/lib/rtl/rtl_source_c.cc b/lib/rtl/rtl_source_c.cc
index 5e3306b..a371464 100644
--- a/lib/rtl/rtl_source_c.cc
+++ b/lib/rtl/rtl_source_c.cc
@@ -32,6 +32,7 @@
#include <boost/assign.hpp>
#include <boost/format.hpp>
+#include <boost/detail/endian.hpp>
#include <boost/algorithm/string.hpp>
#include <stdexcept>
@@ -297,7 +298,7 @@ void rtl_source_c::rtlsdr_callback(unsigned char *buf, uint32_t len)
}
{
- std::lock_guard<std::mutex> lock( _buf_mutex );
+ boost::mutex::scoped_lock lock( _buf_mutex );
int buf_tail = (_buf_head + _buf_used) % _buf_num;
memcpy(_buf[buf_tail], buf, len);
@@ -337,7 +338,7 @@ int rtl_source_c::work( int noutput_items,
gr_complex *out = (gr_complex *)output_items[0];
{
- std::unique_lock<std::mutex> lock( _buf_mutex );
+ boost::mutex::scoped_lock lock( _buf_mutex );
while (_buf_used < 3 && _running) // collect at least 3 buffers
_buf_cond.wait( lock );
@@ -358,7 +359,7 @@ int rtl_source_c::work( int noutput_items,
if (!_samp_avail) {
{
- std::lock_guard<std::mutex> lock( _buf_mutex );
+ boost::mutex::scoped_lock lock( _buf_mutex );
_buf_head = (_buf_head + 1) % _buf_num;
_buf_used--;
diff --git a/lib/rtl/rtl_source_c.h b/lib/rtl/rtl_source_c.h
index de3e349..902b386 100644
--- a/lib/rtl/rtl_source_c.h
+++ b/lib/rtl/rtl_source_c.h
@@ -25,9 +25,8 @@
#include <gnuradio/sync_block.h>
#include <gnuradio/thread/thread.h>
-
-#include <mutex>
-#include <condition_variable>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include "source_iface.h"
@@ -132,8 +131,8 @@ private:
unsigned int _buf_len;
unsigned int _buf_head;
unsigned int _buf_used;
- std::mutex _buf_mutex;
- std::condition_variable _buf_cond;
+ boost::mutex _buf_mutex;
+ boost::condition_variable _buf_cond;
bool _running;
unsigned int _buf_offset;
diff --git a/lib/rtl_tcp/CMakeLists.txt b/lib/rtl_tcp/CMakeLists.txt
index 2de6cee..9f7c201 100644
--- a/lib/rtl_tcp/CMakeLists.txt
+++ b/lib/rtl_tcp/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,15 +21,17 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
-APPEND_LIB_LIST(
- ${Gnuradio-blocks_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(rtl_tcp_srcs
${CMAKE_CURRENT_SOURCE_DIR}/rtl_tcp_source_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${rtl_tcp_srcs})
+#list(APPEND gr_osmosdr_libs ${GNURADIO_BLOCKS_LIBRARIES})
+
diff --git a/lib/rtl_tcp/rtl_tcp_source_c.cc b/lib/rtl_tcp/rtl_tcp_source_c.cc
index af8e300..ecdeee0 100644
--- a/lib/rtl_tcp/rtl_tcp_source_c.cc
+++ b/lib/rtl_tcp/rtl_tcp_source_c.cc
@@ -98,7 +98,7 @@ static int is_error( int perr )
case WSAENOPROTOOPT:
return( perr == ENOPROTOOPT );
default:
- fprintf(stderr,"rtl_tcp_source_c: unknown error %d WS err %d \n", perr, werr );
+ fprintf(stderr,"rtl_tcp_source_f: unknown error %d WS err %d \n", perr, werr );
throw std::runtime_error("internal error");
}
return 0;
@@ -200,7 +200,7 @@ rtl_tcp_source_c::rtl_tcp_source_c(const std::string &args) :
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if( iResult != NO_ERROR ) {
- report_error( "rtl_tcp_source_c WSAStartup", "can't open socket" );
+ report_error( "rtl_tcp_source_f WSAStartup", "can't open socket" );
}
#endif
@@ -219,7 +219,7 @@ rtl_tcp_source_c::rtl_tcp_source_c(const std::string &args) :
// FIXME leaks if report_error throws below
int ret = getaddrinfo(host.c_str(), port_str, &hints, &ip_src);
if (ret != 0)
- report_error("rtl_tcp_source_c/getaddrinfo",
+ report_error("rtl_tcp_source_f/getaddrinfo",
"can't initialize source socket" );
d_temp_buff = new unsigned char[payload_size]; // allow it to hold up to payload_size bytes
@@ -261,8 +261,8 @@ rtl_tcp_source_c::rtl_tcp_source_c(const std::string &args) :
report_error("SO_RCVTIMEO","can't set socket option SO_RCVTIMEO");
#endif // USE_RCV_TIMEO
- if (::connect(d_socket, ip_src->ai_addr, ip_src->ai_addrlen) != 0)
- report_error("rtl_tcp_source_c/connect","can't open TCP connection");
+ while (::connect(d_socket, ip_src->ai_addr, ip_src->ai_addrlen) != 0)
+ ; // FIXME handle errors?
freeaddrinfo(ip_src);
int flag = 1;
diff --git a/lib/sdrplay/CMakeLists.txt b/lib/sdrplay/CMakeLists.txt
index 3d20a6f..382ab33 100644
--- a/lib/sdrplay/CMakeLists.txt
+++ b/lib/sdrplay/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,16 +21,17 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${LIBSDRPLAY_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- ${LIBSDRPLAY_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(sdrplay_srcs
${CMAKE_CURRENT_SOURCE_DIR}/sdrplay_source_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-sdrplay library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${sdrplay_srcs})
+list(APPEND gr_osmosdr_libs ${LIBSDRPLAY_LIBRARIES})
diff --git a/lib/sdrplay/sdrplay_source_c.h b/lib/sdrplay/sdrplay_source_c.h
index b59f44a..2e4631e 100644
--- a/lib/sdrplay/sdrplay_source_c.h
+++ b/lib/sdrplay/sdrplay_source_c.h
@@ -24,9 +24,8 @@
#include <gnuradio/sync_block.h>
#include <gnuradio/thread/thread.h>
-
-#include <mutex>
-#include <condition_variable>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include "osmosdr/ranges.h"
@@ -127,7 +126,7 @@ private:
std::vector< short > _bufi;
std::vector< short > _bufq;
int _buf_offset;
- std::mutex _buf_mutex;
+ boost::mutex _buf_mutex;
bool _running;
bool _uninit;
diff --git a/lib/sink_impl.cc b/lib/sink_impl.cc
index 317855a..d25e860 100644
--- a/lib/sink_impl.cc
+++ b/lib/sink_impl.cc
@@ -48,9 +48,6 @@
#ifdef ENABLE_FREESRP
#include <freesrp_sink_c.h>
#endif
-#ifdef ENABLE_XTRX
-#include "xtrx_sink_c.h"
-#endif
#ifdef ENABLE_FILE
#include "file_sink_c.h"
#endif
@@ -102,9 +99,6 @@ sink_impl::sink_impl( const std::string &args )
#ifdef ENABLE_FREESRP
dev_types.push_back("freesrp");
#endif
-#ifdef ENABLE_XTRX
- dev_types.push_back("xtrx");
-#endif
#ifdef ENABLE_FILE
dev_types.push_back("file");
#endif
@@ -113,13 +107,13 @@ sink_impl::sink_impl( const std::string &args )
<< GR_OSMOSDR_VERSION << " (" << GR_OSMOSDR_LIBVER << ") "
<< "gnuradio " << gr::version() << std::endl;
std::cerr << "built-in sink types: ";
- for (std::string dev_type : dev_types)
+ BOOST_FOREACH(std::string dev_type, dev_types)
std::cerr << dev_type << " ";
std::cerr << std::endl;
- for (std::string arg : arg_list) {
+ BOOST_FOREACH(std::string arg, arg_list) {
dict_t dict = params_to_dict(arg);
- for (std::string dev_type : dev_types) {
+ BOOST_FOREACH(std::string dev_type, dev_types) {
if ( dict.count( dev_type ) ) {
device_specified = true;
break;
@@ -130,40 +124,36 @@ sink_impl::sink_impl( const std::string &args )
if ( ! device_specified ) {
std::vector< std::string > dev_list;
#ifdef ENABLE_UHD
- for (std::string dev : uhd_sink_c::get_devices())
+ BOOST_FOREACH( std::string dev, uhd_sink_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_BLADERF
- for (std::string dev : bladerf_sink_c::get_devices())
+ BOOST_FOREACH( std::string dev, bladerf_sink_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_HACKRF
- for (std::string dev : hackrf_sink_c::get_devices())
+ BOOST_FOREACH( std::string dev, hackrf_sink_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_SOAPY
- for (std::string dev : soapy_sink_c::get_devices())
+ BOOST_FOREACH( std::string dev, soapy_sink_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_REDPITAYA
- for (std::string dev : redpitaya_sink_c::get_devices())
+ BOOST_FOREACH( std::string dev, redpitaya_sink_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_FREESRP
- for (std::string dev : freesrp_sink_c::get_devices())
- dev_list.push_back( dev );
-#endif
-#ifdef ENABLE_XTRX
- for (std::string dev : xtrx_sink_c::get_devices())
+ BOOST_FOREACH( std::string dev, freesrp_sink_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_FILE
- for (std::string dev : file_sink_c::get_devices())
+ BOOST_FOREACH( std::string dev, file_sink_c::get_devices() )
dev_list.push_back( dev );
#endif
// std::cerr << std::endl;
-// for (std::string dev : dev_list)
+// BOOST_FOREACH( std::string dev, dev_list )
// std::cerr << "'" << dev << "'" << std::endl;
if ( dev_list.size() )
@@ -172,12 +162,12 @@ sink_impl::sink_impl( const std::string &args )
throw std::runtime_error("No supported devices found (check the connection and/or udev rules).");
}
- for (std::string arg : arg_list) {
+ BOOST_FOREACH(std::string arg, arg_list) {
dict_t dict = params_to_dict(arg);
// std::cerr << std::endl;
-// for (dict_t::value_type &entry : dict)
+// BOOST_FOREACH( dict_t::value_type &entry, dict )
// std::cerr << "'" << entry.first << "' = '" << entry.second << "'" << std::endl;
sink_iface *iface = NULL;
@@ -219,12 +209,6 @@ sink_impl::sink_impl( const std::string &args )
block = sink; iface = sink.get();
}
#endif
-#ifdef ENABLE_XTRX
- if ( dict.count("xtrx") ) {
- xtrx_sink_c_sptr sink = make_xtrx_sink_c( arg );
- block = sink; iface = sink.get();
- }
-#endif
#ifdef ENABLE_FILE
if ( dict.count("file") ) {
file_sink_c_sptr sink = make_file_sink_c( arg );
@@ -245,13 +229,20 @@ sink_impl::sink_impl( const std::string &args )
if (!_devs.size())
throw std::runtime_error("No devices specified via device arguments.");
+
+ /* Populate the _gain and _gain_mode arrays with the hardware state */
+ BOOST_FOREACH( sink_iface *dev, _devs )
+ for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++) {
+ _gain_mode[dev_chan] = dev->get_gain_mode(dev_chan);
+ _gain[dev_chan] = dev->get_gain(dev_chan);
+ }
}
size_t sink_impl::get_num_channels()
{
size_t channels = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
channels += dev->get_num_channels();
return channels;
@@ -279,13 +270,13 @@ double sink_impl::set_sample_rate(double rate)
if (_devs.empty())
throw std::runtime_error(NO_DEVICES_MSG);
#endif
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
sample_rate = dev->set_sample_rate(rate);
_sample_rate = sample_rate;
}
- return _sample_rate;
+ return sample_rate;
}
double sink_impl::get_sample_rate()
@@ -304,7 +295,7 @@ double sink_impl::get_sample_rate()
osmosdr::freq_range_t sink_impl::get_freq_range( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_freq_range( dev_chan );
@@ -315,7 +306,7 @@ osmosdr::freq_range_t sink_impl::get_freq_range( size_t chan )
double sink_impl::set_center_freq( double freq, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _center_freq[ chan ] != freq ) {
@@ -330,7 +321,7 @@ double sink_impl::set_center_freq( double freq, size_t chan )
double sink_impl::get_center_freq( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_center_freq( dev_chan );
@@ -341,7 +332,7 @@ double sink_impl::get_center_freq( size_t chan )
double sink_impl::set_freq_corr( double ppm, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _freq_corr[ chan ] != ppm ) {
@@ -356,7 +347,7 @@ double sink_impl::set_freq_corr( double ppm, size_t chan )
double sink_impl::get_freq_corr( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_freq_corr( dev_chan );
@@ -367,7 +358,7 @@ double sink_impl::get_freq_corr( size_t chan )
std::vector<std::string> sink_impl::get_gain_names( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain_names( dev_chan );
@@ -378,7 +369,7 @@ std::vector<std::string> sink_impl::get_gain_names( size_t chan )
osmosdr::gain_range_t sink_impl::get_gain_range( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain_range( dev_chan );
@@ -389,7 +380,7 @@ osmosdr::gain_range_t sink_impl::get_gain_range( size_t chan )
osmosdr::gain_range_t sink_impl::get_gain_range( const std::string & name, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain_range( name, dev_chan );
@@ -400,7 +391,7 @@ osmosdr::gain_range_t sink_impl::get_gain_range( const std::string & name, size_
bool sink_impl::set_gain_mode( bool automatic, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _gain_mode[ chan ] != automatic ) {
@@ -418,7 +409,7 @@ bool sink_impl::set_gain_mode( bool automatic, size_t chan )
bool sink_impl::get_gain_mode( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain_mode( dev_chan );
@@ -429,7 +420,7 @@ bool sink_impl::get_gain_mode( size_t chan )
double sink_impl::set_gain( double gain, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _gain[ chan ] != gain ) {
@@ -444,7 +435,7 @@ double sink_impl::set_gain( double gain, size_t chan )
double sink_impl::set_gain( double gain, const std::string & name, size_t chan)
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_gain( gain, name, dev_chan );
@@ -455,7 +446,7 @@ double sink_impl::set_gain( double gain, const std::string & name, size_t chan)
double sink_impl::get_gain( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain( dev_chan );
@@ -466,7 +457,7 @@ double sink_impl::get_gain( size_t chan )
double sink_impl::get_gain( const std::string & name, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain( name, dev_chan );
@@ -477,7 +468,7 @@ double sink_impl::get_gain( const std::string & name, size_t chan )
double sink_impl::set_if_gain( double gain, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _if_gain[ chan ] != gain ) {
@@ -492,7 +483,7 @@ double sink_impl::set_if_gain( double gain, size_t chan )
double sink_impl::set_bb_gain( double gain, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _bb_gain[ chan ] != gain ) {
@@ -507,7 +498,7 @@ double sink_impl::set_bb_gain( double gain, size_t chan )
std::vector< std::string > sink_impl::get_antennas( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_antennas( dev_chan );
@@ -518,7 +509,7 @@ std::vector< std::string > sink_impl::get_antennas( size_t chan )
std::string sink_impl::set_antenna( const std::string & antenna, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _antenna[ chan ] != antenna ) {
@@ -533,7 +524,7 @@ std::string sink_impl::set_antenna( const std::string & antenna, size_t chan )
std::string sink_impl::get_antenna( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_antenna( dev_chan );
@@ -544,7 +535,7 @@ std::string sink_impl::get_antenna( size_t chan )
void sink_impl::set_dc_offset( const std::complex<double> &offset, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
dev->set_dc_offset( offset, dev_chan );
@@ -553,7 +544,7 @@ void sink_impl::set_dc_offset( const std::complex<double> &offset, size_t chan )
void sink_impl::set_iq_balance( const std::complex<double> &balance, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
dev->set_iq_balance( balance, dev_chan );
@@ -562,7 +553,7 @@ void sink_impl::set_iq_balance( const std::complex<double> &balance, size_t chan
double sink_impl::set_bandwidth( double bandwidth, size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _bandwidth[ chan ] != bandwidth || 0.0f == bandwidth ) {
@@ -577,7 +568,7 @@ double sink_impl::set_bandwidth( double bandwidth, size_t chan )
double sink_impl::get_bandwidth( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_bandwidth( dev_chan );
@@ -588,7 +579,7 @@ double sink_impl::get_bandwidth( size_t chan )
osmosdr::freq_range_t sink_impl::get_bandwidth_range( size_t chan )
{
size_t channel = 0;
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_bandwidth_range( dev_chan );
@@ -681,7 +672,7 @@ void sink_impl::set_time_now(const osmosdr::time_spec_t &time_spec, size_t mboar
void sink_impl::set_time_next_pps(const osmosdr::time_spec_t &time_spec)
{
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
{
dev->set_time_next_pps( time_spec );
}
@@ -689,7 +680,7 @@ void sink_impl::set_time_next_pps(const osmosdr::time_spec_t &time_spec)
void sink_impl::set_time_unknown_pps(const osmosdr::time_spec_t &time_spec)
{
- for (sink_iface *dev : _devs)
+ BOOST_FOREACH( sink_iface *dev, _devs )
{
dev->set_time_unknown_pps( time_spec );
}
diff --git a/lib/soapy/CMakeLists.txt b/lib/soapy/CMakeLists.txt
index 7ac4d69..338bcaf 100644
--- a/lib/soapy/CMakeLists.txt
+++ b/lib/soapy/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2015 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,18 +21,19 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${SoapySDR_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- ${SoapySDR_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(soapy_srcs
${CMAKE_CURRENT_SOURCE_DIR}/soapy_common.cc
${CMAKE_CURRENT_SOURCE_DIR}/soapy_source_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/soapy_sink_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${soapy_srcs})
+list(APPEND gr_osmosdr_libs ${SoapySDR_LIBRARIES})
diff --git a/lib/soapy/soapy_common.cc b/lib/soapy/soapy_common.cc
index e241967..0e277e4 100644
--- a/lib/soapy/soapy_common.cc
+++ b/lib/soapy/soapy_common.cc
@@ -36,8 +36,8 @@ osmosdr::gain_range_t soapy_range_to_gain_range(const SoapySDR::Range &r)
return osmosdr::gain_range_t(r.minimum(), r.maximum(), step);
}
-std::mutex &get_soapy_maker_mutex(void)
+boost::mutex &get_soapy_maker_mutex(void)
{
- static std::mutex m;
+ static boost::mutex m;
return m;
}
diff --git a/lib/soapy/soapy_common.h b/lib/soapy/soapy_common.h
index 8adb0db..87e46a5 100644
--- a/lib/soapy/soapy_common.h
+++ b/lib/soapy/soapy_common.h
@@ -23,8 +23,7 @@
#include <osmosdr/ranges.h>
#include <SoapySDR/Types.hpp>
-
-#include <mutex>
+#include <boost/thread/mutex.hpp>
/*!
* Convert a soapy range to a gain range.
@@ -36,6 +35,6 @@ osmosdr::gain_range_t soapy_range_to_gain_range(const SoapySDR::Range &r);
* Global mutex to protect factory routines.
* (optional under 0.5 release above)
*/
-std::mutex &get_soapy_maker_mutex(void);
+boost::mutex &get_soapy_maker_mutex(void);
#endif /* INCLUDED_SOAPY_COMMON_H */
diff --git a/lib/soapy/soapy_sink_c.cc b/lib/soapy/soapy_sink_c.cc
index 4aafc47..b12b8da 100644
--- a/lib/soapy/soapy_sink_c.cc
+++ b/lib/soapy/soapy_sink_c.cc
@@ -63,7 +63,7 @@ soapy_sink_c::soapy_sink_c (const std::string &args)
gr::io_signature::make (0, 0, 0))
{
{
- std::lock_guard<std::mutex> l(get_soapy_maker_mutex());
+ boost::mutex::scoped_lock l(get_soapy_maker_mutex());
_device = SoapySDR::Device::make(params_to_dict(args));
}
_nchan = std::max(1, args_to_io_signature(args)->max_streams());
@@ -75,7 +75,7 @@ soapy_sink_c::soapy_sink_c (const std::string &args)
soapy_sink_c::~soapy_sink_c(void)
{
_device->closeStream(_stream);
- std::lock_guard<std::mutex> l(get_soapy_maker_mutex());
+ boost::mutex::scoped_lock l(get_soapy_maker_mutex());
SoapySDR::Device::unmake(_device);
}
@@ -107,7 +107,7 @@ std::vector<std::string> soapy_sink_c::get_devices()
{
std::vector<std::string> result;
int i = 0;
- for (SoapySDR::Kwargs kw : SoapySDR::Device::enumerate())
+ BOOST_FOREACH(SoapySDR::Kwargs kw, SoapySDR::Device::enumerate())
{
kw["soapy"] = boost::lexical_cast<std::string>(i++);
result.push_back(dict_to_args_string(kw));
@@ -124,12 +124,12 @@ osmosdr::meta_range_t soapy_sink_c::get_sample_rates( void )
{
osmosdr::meta_range_t result;
#ifdef SOAPY_SDR_API_HAS_GET_SAMPLE_RATE_RANGE
- for (const SoapySDR::Range &r : _device->getSampleRateRange(SOAPY_SDR_TX, 0))
+ BOOST_FOREACH(const SoapySDR::Range &r, _device->getSampleRateRange(SOAPY_SDR_TX, 0))
{
result.push_back(osmosdr::range_t(r.minimum(), r.maximum()));
}
#else
- for (const double rate : _device->listSampleRates(SOAPY_SDR_TX, 0))
+ BOOST_FOREACH(const double rate, _device->listSampleRates(SOAPY_SDR_TX, 0))
{
result.push_back(osmosdr::range_t(rate));
}
@@ -151,7 +151,7 @@ double soapy_sink_c::get_sample_rate( void )
osmosdr::freq_range_t soapy_sink_c::get_freq_range( size_t chan)
{
osmosdr::meta_range_t result;
- for (const SoapySDR::Range r : _device->getFrequencyRange(SOAPY_SDR_TX, 0))
+ BOOST_FOREACH(const SoapySDR::Range r, _device->getFrequencyRange(SOAPY_SDR_TX, 0))
{
result.push_back(osmosdr::range_t(r.minimum(), r.maximum()));
}
@@ -309,12 +309,12 @@ osmosdr::freq_range_t soapy_sink_c::get_bandwidth_range( size_t chan)
{
osmosdr::meta_range_t result;
#ifdef SOAPY_SDR_API_HAS_GET_BANDWIDTH_RANGE
- for (const SoapySDR::Range &r : _device->getBandwidthRange(SOAPY_SDR_TX, 0))
+ BOOST_FOREACH(const SoapySDR::Range &r, _device->getBandwidthRange(SOAPY_SDR_TX, 0))
{
result.push_back(osmosdr::range_t(r.minimum(), r.maximum()));
}
#else
- for (const double bw : _device->listBandwidths(SOAPY_SDR_TX, 0))
+ BOOST_FOREACH(const double bw, _device->listBandwidths(SOAPY_SDR_TX, 0))
{
result.push_back(osmosdr::range_t(bw));
}
diff --git a/lib/soapy/soapy_source_c.cc b/lib/soapy/soapy_source_c.cc
index 4dc9efc..a645361 100644
--- a/lib/soapy/soapy_source_c.cc
+++ b/lib/soapy/soapy_source_c.cc
@@ -64,7 +64,7 @@ soapy_source_c::soapy_source_c (const std::string &args)
args_to_io_signature(args))
{
{
- std::lock_guard<std::mutex> l(get_soapy_maker_mutex());
+ boost::mutex::scoped_lock l(get_soapy_maker_mutex());
_device = SoapySDR::Device::make(params_to_dict(args));
}
_nchan = std::max(1, args_to_io_signature(args)->max_streams());
@@ -76,7 +76,7 @@ soapy_source_c::soapy_source_c (const std::string &args)
soapy_source_c::~soapy_source_c(void)
{
_device->closeStream(_stream);
- std::lock_guard<std::mutex> l(get_soapy_maker_mutex());
+ boost::mutex::scoped_lock l(get_soapy_maker_mutex());
SoapySDR::Device::unmake(_device);
}
@@ -96,14 +96,9 @@ int soapy_source_c::work( int noutput_items,
{
int flags = 0;
long long timeNs = 0;
- int ret;
- int retries = 1;
-
- do {
- ret = _device->readStream(
- _stream, &output_items[0],
- noutput_items, flags, timeNs);
- } while (retries-- && (ret == SOAPY_SDR_OVERFLOW));
+ int ret = _device->readStream(
+ _stream, &output_items[0],
+ noutput_items, flags, timeNs);
if (ret < 0) return 0; //call again
return ret;
@@ -113,7 +108,7 @@ std::vector<std::string> soapy_source_c::get_devices()
{
std::vector<std::string> result;
int i = 0;
- for (SoapySDR::Kwargs kw : SoapySDR::Device::enumerate())
+ BOOST_FOREACH(SoapySDR::Kwargs kw, SoapySDR::Device::enumerate())
{
kw["soapy"] = boost::lexical_cast<std::string>(i++);
result.push_back(dict_to_args_string(kw));
@@ -130,12 +125,12 @@ osmosdr::meta_range_t soapy_source_c::get_sample_rates( void )
{
osmosdr::meta_range_t result;
#ifdef SOAPY_SDR_API_HAS_GET_SAMPLE_RATE_RANGE
- for (const SoapySDR::Range &r : _device->getSampleRateRange(SOAPY_SDR_RX, 0))
+ BOOST_FOREACH(const SoapySDR::Range &r, _device->getSampleRateRange(SOAPY_SDR_RX, 0))
{
result.push_back(osmosdr::range_t(r.minimum(), r.maximum()));
}
#else
- for (const double rate : _device->listSampleRates(SOAPY_SDR_RX, 0))
+ BOOST_FOREACH(const double rate, _device->listSampleRates(SOAPY_SDR_RX, 0))
{
result.push_back(osmosdr::range_t(rate));
}
@@ -157,7 +152,7 @@ double soapy_source_c::get_sample_rate( void )
osmosdr::freq_range_t soapy_source_c::get_freq_range( size_t chan )
{
osmosdr::meta_range_t result;
- for (const SoapySDR::Range r : _device->getFrequencyRange(SOAPY_SDR_RX, 0))
+ BOOST_FOREACH(const SoapySDR::Range r, _device->getFrequencyRange(SOAPY_SDR_RX, 0))
{
result.push_back(osmosdr::range_t(r.minimum(), r.maximum()));
}
@@ -338,12 +333,12 @@ osmosdr::freq_range_t soapy_source_c::get_bandwidth_range( size_t chan )
{
osmosdr::meta_range_t result;
#ifdef SOAPY_SDR_API_HAS_GET_BANDWIDTH_RANGE
- for (const SoapySDR::Range &r : _device->getBandwidthRange(SOAPY_SDR_RX, 0))
+ BOOST_FOREACH(const SoapySDR::Range &r, _device->getBandwidthRange(SOAPY_SDR_RX, 0))
{
result.push_back(osmosdr::range_t(r.minimum(), r.maximum()));
}
#else
- for (const double bw : _device->listBandwidths(SOAPY_SDR_RX, 0))
+ BOOST_FOREACH(const double bw, _device->listBandwidths(SOAPY_SDR_RX, 0))
{
result.push_back(osmosdr::range_t(bw));
}
diff --git a/lib/source_impl.cc b/lib/source_impl.cc
index 8f2028b..f9a7e64 100644
--- a/lib/source_impl.cc
+++ b/lib/source_impl.cc
@@ -32,6 +32,10 @@
#include <gnuradio/blocks/throttle.h>
#include <gnuradio/constants.h>
+#ifdef ENABLE_OSMOSDR
+#include <osmosdr_src_c.h>
+#endif
+
#ifdef ENABLE_FCD
#include <fcd_source_c.h>
#endif
@@ -52,6 +56,10 @@
#include <uhd_source_c.h>
#endif
+#ifdef ENABLE_MIRI
+#include <miri_source_c.h>
+#endif
+
#ifdef ENABLE_SDRPLAY
#include <sdrplay_source_c.h>
#endif
@@ -72,10 +80,6 @@
#include <airspy_source_c.h>
#endif
-#ifdef ENABLE_AIRSPYHF
-#include <airspyhf_source_c.h>
-#endif
-
#ifdef ENABLE_SOAPY
#include <soapy_source_c.h>
#endif
@@ -88,10 +92,6 @@
#include <freesrp_source_c.h>
#endif
-#ifdef ENABLE_XTRX
-#include <xtrx_source_c.h>
-#endif
-
#include "arg_helpers.h"
#include "source_impl.h"
@@ -124,6 +124,9 @@ source_impl::source_impl( const std::string &args )
#ifdef ENABLE_FILE
dev_types.push_back("file");
#endif
+#ifdef ENABLE_OSMOSDR
+ dev_types.push_back("osmosdr");
+#endif
#ifdef ENABLE_FCD
dev_types.push_back("fcd");
#endif
@@ -136,6 +139,9 @@ source_impl::source_impl( const std::string &args )
#ifdef ENABLE_UHD
dev_types.push_back("uhd");
#endif
+#ifdef ENABLE_MIRI
+ dev_types.push_back("miri");
+#endif
#ifdef ENABLE_SDRPLAY
dev_types.push_back("sdrplay");
#endif
@@ -151,9 +157,6 @@ source_impl::source_impl( const std::string &args )
#ifdef ENABLE_AIRSPY
dev_types.push_back("airspy");
#endif
-#ifdef ENABLE_AIRSPYHF
- dev_types.push_back("airspyhf");
-#endif
#ifdef ENABLE_SOAPY
dev_types.push_back("soapy");
#endif
@@ -163,14 +166,11 @@ source_impl::source_impl( const std::string &args )
#ifdef ENABLE_FREESRP
dev_types.push_back("freesrp");
#endif
-#ifdef ENABLE_XTRX
- dev_types.push_back("xtrx");
-#endif
std::cerr << "gr-osmosdr "
<< GR_OSMOSDR_VERSION << " (" << GR_OSMOSDR_LIBVER << ") "
<< "gnuradio " << gr::version() << std::endl;
std::cerr << "built-in source types: ";
- for (std::string dev_type : dev_types)
+ BOOST_FOREACH(std::string dev_type, dev_types)
std::cerr << dev_type << " ";
std::cerr << std::endl;
@@ -181,9 +181,9 @@ source_impl::source_impl( const std::string &args )
dev_types.push_back("cloudiq");
#endif
- for (std::string arg : arg_list) {
+ BOOST_FOREACH(std::string arg, arg_list) {
dict_t dict = params_to_dict(arg);
- for (std::string dev_type : dev_types) {
+ BOOST_FOREACH(std::string dev_type, dev_types) {
if ( dict.count( dev_type ) ) {
device_specified = true;
break;
@@ -191,63 +191,76 @@ source_impl::source_impl( const std::string &args )
}
}
+ bool force_arg = false;
+ int force_val = 0;
+
+ if (arg_list.size() <= 2) {
+ BOOST_FOREACH(std::string arg, arg_list) {
+ if ( arg.find( "numchan=" ) == 0 ) {
+ pair_t pair = param_to_pair( arg );
+ force_arg = true;
+ force_val = boost::lexical_cast<size_t>( pair.second );
+ }
+ }
+ }
+
if ( ! device_specified ) {
std::vector< std::string > dev_list;
+#ifdef ENABLE_OSMOSDR
+ BOOST_FOREACH( std::string dev, osmosdr_src_c::get_devices() )
+ dev_list.push_back( dev );
+#endif
#ifdef ENABLE_FCD
- for (std::string dev : fcd_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, fcd_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_RTL
- for (std::string dev : rtl_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, rtl_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_UHD
- for (std::string dev : uhd_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, uhd_source_c::get_devices() )
+ dev_list.push_back( dev );
+#endif
+#ifdef ENABLE_MIRI
+ BOOST_FOREACH( std::string dev, miri_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_SDRPLAY
- for (std::string dev : sdrplay_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, sdrplay_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_BLADERF
- for (std::string dev : bladerf_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, bladerf_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_RFSPACE
- for (std::string dev : rfspace_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, rfspace_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_HACKRF
- for (std::string dev : hackrf_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, hackrf_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_AIRSPY
- for (std::string dev : airspy_source_c::get_devices())
- dev_list.push_back( dev );
-#endif
-#ifdef ENABLE_AIRSPYHF
- for (std::string dev : airspyhf_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, airspy_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_SOAPY
- for (std::string dev : soapy_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, soapy_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_REDPITAYA
- for (std::string dev : redpitaya_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, redpitaya_source_c::get_devices() )
dev_list.push_back( dev );
#endif
#ifdef ENABLE_FREESRP
- for (std::string dev : freesrp_source_c::get_devices())
- dev_list.push_back( dev );
-#endif
-#ifdef ENABLE_XTRX
- for (std::string dev : xtrx_source_c::get_devices())
+ BOOST_FOREACH( std::string dev, freesrp_source_c::get_devices() )
dev_list.push_back( dev );
#endif
// std::cerr << std::endl;
-// for (std::string dev : dev_list)
+// BOOST_FOREACH( std::string dev, dev_list )
// std::cerr << "'" << dev << "'" << std::endl;
if ( dev_list.size() )
@@ -256,17 +269,27 @@ source_impl::source_impl( const std::string &args )
throw std::runtime_error("No supported devices found (check the connection and/or udev rules).");
}
- for (std::string arg : arg_list) {
+ BOOST_FOREACH(std::string arg, arg_list) {
+
+ if(force_arg)
+ arg += ",nchan=" + std::to_string(force_val);
dict_t dict = params_to_dict(arg);
// std::cerr << std::endl;
-// for (dict_t::value_type &entry : dict)
+// BOOST_FOREACH( dict_t::value_type &entry, dict )
// std::cerr << "'" << entry.first << "' = '" << entry.second << "'" << std::endl;
source_iface *iface = NULL;
gr::basic_block_sptr block;
+#ifdef ENABLE_OSMOSDR
+ if ( dict.count("osmosdr") ) {
+ osmosdr_src_c_sptr src = osmosdr_make_src_c( arg );
+ block = src; iface = src.get();
+ }
+#endif
+
#ifdef ENABLE_FCD
if ( dict.count("fcd") ) {
fcd_source_c_sptr src = make_fcd_source_c( arg );
@@ -302,6 +325,13 @@ source_impl::source_impl( const std::string &args )
}
#endif
+#ifdef ENABLE_MIRI
+ if ( dict.count("miri") ) {
+ miri_source_c_sptr src = make_miri_source_c( arg );
+ block = src; iface = src.get();
+ }
+#endif
+
#ifdef ENABLE_SDRPLAY
if ( dict.count("sdrplay") ) {
sdrplay_source_c_sptr src = make_sdrplay_source_c( arg );
@@ -341,13 +371,6 @@ source_impl::source_impl( const std::string &args )
}
#endif
-#ifdef ENABLE_AIRSPYHF
- if ( dict.count("airspyhf") ) {
- airspyhf_source_c_sptr src = make_airspyhf_source_c( arg );
- block = src; iface = src.get();
- }
-#endif
-
#ifdef ENABLE_SOAPY
if ( dict.count("soapy") ) {
soapy_source_c_sptr src = make_soapy_source_c( arg );
@@ -369,13 +392,6 @@ source_impl::source_impl( const std::string &args )
}
#endif
-#ifdef ENABLE_XTRX
- if ( dict.count("xtrx") ) {
- xtrx_source_c_sptr src = make_xtrx_source_c( arg );
- block = src; iface = src.get();
- }
-#endif
-
if ( iface != NULL && long(block.get()) != 0 ) {
_devs.push_back( iface );
@@ -403,13 +419,20 @@ source_impl::source_impl( const std::string &args )
if (!_devs.size())
throw std::runtime_error("No devices specified via device arguments.");
+
+ /* Populate the _gain and _gain_mode arrays with the hardware state */
+ BOOST_FOREACH( source_iface *dev, _devs )
+ for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++) {
+ _gain_mode[dev_chan] = dev->get_gain_mode(dev_chan);
+ _gain[dev_chan] = dev->get_gain(dev_chan);
+ }
}
size_t source_impl::get_num_channels()
{
size_t channels = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
channels += dev->get_num_channels();
return channels;
@@ -418,7 +441,7 @@ size_t source_impl::get_num_channels()
bool source_impl::seek( long seek_point, int whence, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->seek( seek_point, whence, dev_chan );
@@ -448,12 +471,12 @@ double source_impl::set_sample_rate(double rate)
if (_devs.empty())
throw std::runtime_error(NO_DEVICES_MSG);
#endif
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
sample_rate = dev->set_sample_rate(rate);
#ifdef HAVE_IQBALANCE
size_t channel = 0;
- for (source_iface *dev : _devs) {
+ BOOST_FOREACH( source_iface *dev, _devs ) {
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++) {
if ( channel < _iq_opt.size() ) {
gr::iqbalance::optimize_c *opt = _iq_opt[channel];
@@ -472,7 +495,7 @@ double source_impl::set_sample_rate(double rate)
_sample_rate = sample_rate;
}
- return _sample_rate;
+ return sample_rate;
}
double source_impl::get_sample_rate()
@@ -491,7 +514,7 @@ double source_impl::get_sample_rate()
osmosdr::freq_range_t source_impl::get_freq_range( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_freq_range( dev_chan );
@@ -502,7 +525,7 @@ osmosdr::freq_range_t source_impl::get_freq_range( size_t chan )
double source_impl::set_center_freq( double freq, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _center_freq[ chan ] != freq ) {
@@ -517,7 +540,7 @@ double source_impl::set_center_freq( double freq, size_t chan )
double source_impl::get_center_freq( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_center_freq( dev_chan );
@@ -528,7 +551,7 @@ double source_impl::get_center_freq( size_t chan )
double source_impl::set_freq_corr( double ppm, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _freq_corr[ chan ] != ppm ) {
@@ -543,7 +566,7 @@ double source_impl::set_freq_corr( double ppm, size_t chan )
double source_impl::get_freq_corr( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_freq_corr( dev_chan );
@@ -554,7 +577,7 @@ double source_impl::get_freq_corr( size_t chan )
std::vector<std::string> source_impl::get_gain_names( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain_names( dev_chan );
@@ -565,7 +588,7 @@ std::vector<std::string> source_impl::get_gain_names( size_t chan )
osmosdr::gain_range_t source_impl::get_gain_range( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain_range( dev_chan );
@@ -576,7 +599,7 @@ osmosdr::gain_range_t source_impl::get_gain_range( size_t chan )
osmosdr::gain_range_t source_impl::get_gain_range( const std::string & name, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain_range( name, dev_chan );
@@ -587,7 +610,7 @@ osmosdr::gain_range_t source_impl::get_gain_range( const std::string & name, siz
bool source_impl::set_gain_mode( bool automatic, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _gain_mode[ chan ] != automatic ) {
@@ -605,7 +628,7 @@ bool source_impl::set_gain_mode( bool automatic, size_t chan )
bool source_impl::get_gain_mode( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain_mode( dev_chan );
@@ -616,7 +639,7 @@ bool source_impl::get_gain_mode( size_t chan )
double source_impl::set_gain( double gain, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _gain[ chan ] != gain ) {
@@ -631,7 +654,7 @@ double source_impl::set_gain( double gain, size_t chan )
double source_impl::set_gain( double gain, const std::string & name, size_t chan)
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_gain( gain, name, dev_chan );
@@ -642,7 +665,7 @@ double source_impl::set_gain( double gain, const std::string & name, size_t chan
double source_impl::get_gain( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain( dev_chan );
@@ -653,7 +676,7 @@ double source_impl::get_gain( size_t chan )
double source_impl::get_gain( const std::string & name, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_gain( name, dev_chan );
@@ -664,7 +687,7 @@ double source_impl::get_gain( const std::string & name, size_t chan )
double source_impl::set_if_gain( double gain, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _if_gain[ chan ] != gain ) {
@@ -679,7 +702,7 @@ double source_impl::set_if_gain( double gain, size_t chan )
double source_impl::set_bb_gain( double gain, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _bb_gain[ chan ] != gain ) {
@@ -694,7 +717,7 @@ double source_impl::set_bb_gain( double gain, size_t chan )
std::vector< std::string > source_impl::get_antennas( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_antennas( dev_chan );
@@ -705,7 +728,7 @@ std::vector< std::string > source_impl::get_antennas( size_t chan )
std::string source_impl::set_antenna( const std::string & antenna, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _antenna[ chan ] != antenna ) {
@@ -720,7 +743,7 @@ std::string source_impl::set_antenna( const std::string & antenna, size_t chan )
std::string source_impl::get_antenna( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_antenna( dev_chan );
@@ -731,7 +754,7 @@ std::string source_impl::get_antenna( size_t chan )
void source_impl::set_dc_offset_mode( int mode, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
dev->set_dc_offset_mode( mode, dev_chan );
@@ -740,7 +763,7 @@ void source_impl::set_dc_offset_mode( int mode, size_t chan )
void source_impl::set_dc_offset( const std::complex<double> &offset, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
dev->set_dc_offset( offset, dev_chan );
@@ -750,7 +773,7 @@ void source_impl::set_iq_balance_mode( int mode, size_t chan )
{
size_t channel = 0;
#ifdef HAVE_IQBALANCE
- for (source_iface *dev : _devs) {
+ BOOST_FOREACH( source_iface *dev, _devs ) {
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++) {
if ( chan == channel++ ) {
if ( chan < _iq_opt.size() && chan < _iq_fix.size() ) {
@@ -780,7 +803,7 @@ void source_impl::set_iq_balance_mode( int mode, size_t chan )
}
}
#else
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_iq_balance_mode( mode, dev_chan );
@@ -791,7 +814,7 @@ void source_impl::set_iq_balance( const std::complex<double> &balance, size_t ch
{
size_t channel = 0;
#ifdef HAVE_IQBALANCE
- for (source_iface *dev : _devs) {
+ BOOST_FOREACH( source_iface *dev, _devs ) {
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++) {
if ( chan == channel++ ) {
if ( chan < _iq_opt.size() && chan < _iq_fix.size() ) {
@@ -807,7 +830,7 @@ void source_impl::set_iq_balance( const std::complex<double> &balance, size_t ch
}
}
#else
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_iq_balance( balance, dev_chan );
@@ -817,7 +840,7 @@ void source_impl::set_iq_balance( const std::complex<double> &balance, size_t ch
double source_impl::set_bandwidth( double bandwidth, size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ ) {
if ( _bandwidth[ chan ] != bandwidth || 0.0f == bandwidth ) {
@@ -832,7 +855,7 @@ double source_impl::set_bandwidth( double bandwidth, size_t chan )
double source_impl::get_bandwidth( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_bandwidth( dev_chan );
@@ -843,7 +866,7 @@ double source_impl::get_bandwidth( size_t chan )
osmosdr::freq_range_t source_impl::get_bandwidth_range( size_t chan )
{
size_t channel = 0;
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->get_bandwidth_range( dev_chan );
@@ -936,7 +959,7 @@ void source_impl::set_time_now(const osmosdr::time_spec_t &time_spec, size_t mbo
void source_impl::set_time_next_pps(const osmosdr::time_spec_t &time_spec)
{
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
{
dev->set_time_next_pps( time_spec );
}
@@ -944,7 +967,7 @@ void source_impl::set_time_next_pps(const osmosdr::time_spec_t &time_spec)
void source_impl::set_time_unknown_pps(const osmosdr::time_spec_t &time_spec)
{
- for (source_iface *dev : _devs)
+ BOOST_FOREACH( source_iface *dev, _devs )
{
dev->set_time_unknown_pps( time_spec );
}
diff --git a/lib/uhd/CMakeLists.txt b/lib/uhd/CMakeLists.txt
index 0ab6508..aba5c77 100644
--- a/lib/uhd/CMakeLists.txt
+++ b/lib/uhd/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2012 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
@@ -21,19 +21,19 @@
# This file included, use CMake directory variables
########################################################################
-target_include_directories(gnuradio-osmosdr PRIVATE
+include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
- ${gnuradio-uhd_INCLUDE_DIRS}
+ ${GNURADIO_UHD_INCLUDE_DIRS}
${UHD_INCLUDE_DIRS}
)
-APPEND_LIB_LIST(
- gnuradio::gnuradio-uhd
- ${UHD_LIBRARIES}
-)
-
-list(APPEND gr_osmosdr_srcs
+set(uhd_srcs
${CMAKE_CURRENT_SOURCE_DIR}/uhd_sink_c.cc
${CMAKE_CURRENT_SOURCE_DIR}/uhd_source_c.cc
)
-set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${uhd_srcs})
+list(APPEND gr_osmosdr_libs ${GNURADIO_UHD_LIBRARIES} ${UHD_LIBRARIES})
diff --git a/lib/uhd/uhd_sink_c.cc b/lib/uhd/uhd_sink_c.cc
index 8698f4c..a154556 100644
--- a/lib/uhd/uhd_sink_c.cc
+++ b/lib/uhd/uhd_sink_c.cc
@@ -18,6 +18,7 @@
* Boston, MA 02110-1301, USA.
*/
+#include <boost/foreach.hpp>
#include <boost/assign.hpp>
#include <boost/algorithm/string.hpp>
@@ -70,7 +71,7 @@ uhd_sink_c::uhd_sink_c(const std::string &args) :
_lo_offset = boost::lexical_cast< double >( dict["lo_offset"] );
std::string arguments; // rebuild argument string without internal arguments
- for (dict_t::value_type &entry : dict)
+ BOOST_FOREACH( dict_t::value_type &entry, dict )
{
if ( "cpu_format" == entry.first ||
"otw_format" == entry.first ||
@@ -134,7 +135,7 @@ std::vector< std::string > uhd_sink_c::get_devices()
std::vector< std::string > devices;
uhd::device_addr_t hint;
- for (const uhd::device_addr_t &dev : uhd::device::find(hint))
+ BOOST_FOREACH(const uhd::device_addr_t &dev, uhd::device::find(hint))
{
std::string args = "uhd," + dev.to_string();
@@ -189,7 +190,7 @@ osmosdr::meta_range_t uhd_sink_c::get_sample_rates( void )
{
osmosdr::meta_range_t rates;
- for (uhd::range_t rate : _snk->get_samp_rates())
+ BOOST_FOREACH( uhd::range_t rate, _snk->get_samp_rates() )
rates += osmosdr::range_t( rate.start(), rate.stop(), rate.step() );
return rates;
@@ -210,7 +211,7 @@ osmosdr::freq_range_t uhd_sink_c::get_freq_range( size_t chan )
{
osmosdr::freq_range_t range;
- for (uhd::range_t freq : _snk->get_freq_range(chan))
+ BOOST_FOREACH( uhd::range_t freq, _snk->get_freq_range(chan) )
range += osmosdr::range_t( freq.start(), freq.stop(), freq.step() );
return range;
@@ -259,7 +260,7 @@ osmosdr::gain_range_t uhd_sink_c::get_gain_range( size_t chan )
{
osmosdr::gain_range_t range;
- for (uhd::range_t gain : _snk->get_gain_range(chan))
+ BOOST_FOREACH( uhd::range_t gain, _snk->get_gain_range(chan) )
range += osmosdr::range_t( gain.start(), gain.stop(), gain.step() );
return range;
@@ -269,7 +270,7 @@ osmosdr::gain_range_t uhd_sink_c::get_gain_range( const std::string & name, size
{
osmosdr::gain_range_t range;
- for (uhd::range_t gain : _snk->get_gain_range(name, chan))
+ BOOST_FOREACH( uhd::range_t gain, _snk->get_gain_range(name, chan) )
range += osmosdr::range_t( gain.start(), gain.stop(), gain.step() );
return range;
@@ -350,7 +351,7 @@ osmosdr::freq_range_t uhd_sink_c::get_bandwidth_range( size_t chan )
{
osmosdr::freq_range_t bandwidths;
- for (uhd::range_t bw : _snk->get_bandwidth_range(chan))
+ BOOST_FOREACH( uhd::range_t bw, _snk->get_bandwidth_range(chan) )
bandwidths += osmosdr::range_t( bw.start(), bw.stop(), bw.step() );
return bandwidths;
diff --git a/lib/uhd/uhd_source_c.cc b/lib/uhd/uhd_source_c.cc
index f9f9fdd..fc13017 100644
--- a/lib/uhd/uhd_source_c.cc
+++ b/lib/uhd/uhd_source_c.cc
@@ -18,6 +18,7 @@
* Boston, MA 02110-1301, USA.
*/
+#include <boost/foreach.hpp>
#include <boost/assign.hpp>
#include <boost/algorithm/string.hpp>
@@ -71,7 +72,7 @@ uhd_source_c::uhd_source_c(const std::string &args) :
_lo_offset = boost::lexical_cast< double >( dict["lo_offset"] );
std::string arguments; // rebuild argument string without internal arguments
- for (dict_t::value_type &entry : dict)
+ BOOST_FOREACH( dict_t::value_type &entry, dict )
{
if ( "cpu_format" == entry.first ||
"otw_format" == entry.first ||
@@ -135,7 +136,7 @@ std::vector< std::string > uhd_source_c::get_devices()
std::vector< std::string > devices;
uhd::device_addr_t hint;
- for (const uhd::device_addr_t &dev : uhd::device::find(hint))
+ BOOST_FOREACH(const uhd::device_addr_t &dev, uhd::device::find(hint))
{
std::string args = "uhd," + dev.to_string();
@@ -190,7 +191,7 @@ osmosdr::meta_range_t uhd_source_c::get_sample_rates( void )
{
osmosdr::meta_range_t rates;
- for (uhd::range_t rate : _src->get_samp_rates())
+ BOOST_FOREACH( uhd::range_t rate, _src->get_samp_rates() )
rates += osmosdr::range_t( rate.start(), rate.stop(), rate.step() );
return rates;
@@ -211,7 +212,7 @@ osmosdr::freq_range_t uhd_source_c::get_freq_range( size_t chan )
{
osmosdr::freq_range_t range;
- for (uhd::range_t freq : _src->get_freq_range(chan))
+ BOOST_FOREACH( uhd::range_t freq, _src->get_freq_range(chan) )
range += osmosdr::range_t( freq.start(), freq.stop(), freq.step() );
return range;
@@ -260,7 +261,7 @@ osmosdr::gain_range_t uhd_source_c::get_gain_range( size_t chan )
{
osmosdr::gain_range_t range;
- for (uhd::range_t gain : _src->get_gain_range(chan))
+ BOOST_FOREACH( uhd::range_t gain, _src->get_gain_range(chan) )
range += osmosdr::range_t( gain.start(), gain.stop(), gain.step() );
return range;
@@ -270,7 +271,7 @@ osmosdr::gain_range_t uhd_source_c::get_gain_range( const std::string & name, si
{
osmosdr::gain_range_t range;
- for (uhd::range_t gain : _src->get_gain_range(name, chan))
+ BOOST_FOREACH( uhd::range_t gain, _src->get_gain_range(name, chan) )
range += osmosdr::range_t( gain.start(), gain.stop(), gain.step() );
return range;
@@ -382,7 +383,7 @@ osmosdr::freq_range_t uhd_source_c::get_bandwidth_range( size_t chan )
{
osmosdr::freq_range_t bandwidths;
- for (uhd::range_t bw : _src->get_bandwidth_range(chan))
+ BOOST_FOREACH( uhd::range_t bw, _src->get_bandwidth_range(chan) )
bandwidths += osmosdr::range_t( bw.start(), bw.stop(), bw.step() );
return bandwidths;
diff --git a/lib/xtrx/xtrx_obj.cc b/lib/xtrx/xtrx_obj.cc
deleted file mode 100644
index 016b420..0000000
--- a/lib/xtrx/xtrx_obj.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2017 Sergey Kostanbaev <sergey.kostanbaev@fairwaves.co>
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-#include "xtrx_obj.h"
-#include <iostream>
-#include <sstream>
-#include <boost/thread.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/thread/mutex.hpp>
-
-static std::map<std::string, xtrx_obj_sptr> s_objects;
-
-xtrx_obj_sptr xtrx_obj::get(const char* xtrx_dev,
- unsigned loglevel,
- bool lmsreset)
-{
- std::map<std::string, xtrx_obj_sptr>::iterator i;
- std::string name(xtrx_dev);
-
- i = s_objects.find(name);
- if (i == s_objects.end()) {
- // No such object
- s_objects[name].reset(new xtrx_obj(name, loglevel, lmsreset));
- }
-
- return s_objects[name];
-}
-
-void xtrx_obj::clear_all()
-{
- s_objects.clear();
-}
-
-std::vector<std::string> xtrx_obj::get_devices()
-{
- std::vector<std::string> devices;
- // TODO
- devices.push_back("/dev/xtrx0");
- return devices;
-}
-
-
-xtrx_obj::xtrx_obj(const std::string &path, unsigned loglevel, bool lmsreset)
- : _run(false)
- , _vio(0)
- , _sink_rate(0)
- , _sink_master(0)
- , _source_rate(0)
- , _source_master(0)
- , _flags(0)
-{
- unsigned xtrxflag = (loglevel & XTRX_O_LOGLVL_MASK) | ((lmsreset) ? XTRX_O_RESET : 0);
- std::cerr << "xtrx_obj::xtrx_obj = " << xtrxflag << std::endl;
-
- int res = xtrx_open_string(path.c_str(), &_obj);
- if (res < 0) {
- std::stringstream message;
- message << "Couldn't open " ": Error: " << -res;
-
- throw std::runtime_error( message.str() );
- }
-
- _devices = res;
-}
-
-double xtrx_obj::set_smaplerate(double rate, double master, bool sink, unsigned flags)
-{
- boost::mutex::scoped_lock lock(mtx);
-
- if (sink) {
- _sink_rate = rate;
- _sink_master = master;
- } else {
- _source_rate = rate;
- _source_master = master;
- }
- _flags |= flags | XTRX_SAMPLERATE_FORCE_UPDATE;
-
- if (_sink_master != 0 && _source_master != 0 && _sink_master != _source_master) {
- std::stringstream message;
- message << "Can't operate on diferrent master settings for XTRX sink and source"
- " sink_master " << _sink_master << " source_master" << _source_master;
-
- throw std::runtime_error( message.str() );
- }
-
- double rxrate = 0, txrate = 0;
- double actmaster = (_source_master > 0) ? _source_master : _sink_master;
- int res = xtrx_set_samplerate(_obj,
- actmaster,
- _source_rate,
- _sink_rate,
- _flags,
- NULL,
- &rxrate,
- &txrate);
- if (res) {
- std::cerr << "Unable to set samplerate, error=" << res << std::endl;
- if (sink)
- return _sink_rate;
- return _source_rate;
- }
-
- if (_vio) {
- xtrx_val_set(_obj, XTRX_TRX, XTRX_CH_AB, XTRX_LMS7_VIO, _vio);
- }
-
- if (sink)
- return txrate;
- return rxrate;
-}
-
-xtrx_obj::~xtrx_obj()
-{
- if (_obj) {
- if (_run) {
- //boost::mutex::scoped_lock lock(mtx);
- xtrx_stop(_obj, XTRX_TRX);
- }
- xtrx_close(_obj);
- }
-}
diff --git a/lib/xtrx/xtrx_obj.h b/lib/xtrx/xtrx_obj.h
deleted file mode 100644
index e26947d..0000000
--- a/lib/xtrx/xtrx_obj.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2017 Sergey Kostanbaev <sergey.kostanbaev@fairwaves.co>
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-#ifndef XTRX_OBJ_H
-#define XTRX_OBJ_H
-
-#include <boost/shared_ptr.hpp>
-#include <xtrx_api.h>
-#include <map>
-#include <vector>
-#include <boost/thread/mutex.hpp>
-
-class xtrx_obj;
-
-typedef boost::shared_ptr<xtrx_obj> xtrx_obj_sptr;
-
-class xtrx_obj
-{
-public:
- xtrx_obj(const std::string& path, unsigned loglevel, bool lmsreset);
- ~xtrx_obj();
-
- static std::vector<std::string> get_devices();
-
- static xtrx_obj_sptr get(const char* xtrx_dev,
- unsigned loglevel,
- bool lmsreset);
- static void clear_all();
-
- xtrx_dev* dev() { return _obj; }
- unsigned dev_count() { return _devices; }
-
- double set_smaplerate(double rate, double master, bool sink, unsigned flags);
-
- void set_vio(unsigned vio) { _vio = vio; }
-
- boost::mutex mtx;
-protected:
- xtrx_dev* _obj;
- bool _run;
- unsigned _vio;
-
- double _sink_rate;
- double _sink_master;
- double _source_rate;
- double _source_master;
-
- unsigned _flags;
- unsigned _devices;
-};
-
-#endif // XTRX_OBJ_H
diff --git a/lib/xtrx/xtrx_sink_c.cc b/lib/xtrx/xtrx_sink_c.cc
deleted file mode 100644
index 5253311..0000000
--- a/lib/xtrx/xtrx_sink_c.cc
+++ /dev/null
@@ -1,505 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2016,2017 Sergey Kostanbaev <sergey.kostanbaev@fairwaves.co>
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-#include <fstream>
-#include <string>
-#include <sstream>
-#include <map>
-
-#include <boost/assign.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/thread.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/thread/mutex.hpp>
-
-#include <gnuradio/io_signature.h>
-#include <gnuradio/blocks/deinterleave.h>
-#include <gnuradio/blocks/float_to_complex.h>
-
-#include "xtrx_sink_c.h"
-
-#include "arg_helpers.h"
-
-static const int max_burstsz = 4096;
-using namespace boost::assign;
-
-xtrx_sink_c_sptr make_xtrx_sink_c(const std::string &args)
-{
- return gnuradio::get_initial_sptr(new xtrx_sink_c(args));
-}
-
-static size_t parse_nchan(const std::string &args)
-{
- size_t nchan = 1;
-
- dict_t dict = params_to_dict(args);
-
- if (dict.count("nchan"))
- nchan = boost::lexical_cast< size_t >( dict["nchan"] );
-
- if (nchan < 1)
- nchan = 1;
-
- return nchan;
-}
-
-xtrx_sink_c::xtrx_sink_c(const std::string &args) :
- gr::sync_block("xtrx_sink_c",
- gr::io_signature::make(parse_nchan(args),
- parse_nchan(args),
- sizeof(gr_complex)),
- gr::io_signature::make(0, 0, 0)),
- _sample_flags(0),
- _rate(0),
- _master(0),
- _freq(0),
- _corr(0),
- _bandwidth(0),
- _dsp(0),
- _auto_gain(false),
- _otw(XTRX_WF_16),
- _mimo_mode(false),
- _gain_tx(0),
- _channels(parse_nchan(args)),
- _ts(8192),
- _swap_ab(false),
- _swap_iq(false),
- _tdd(false),
- _allow_dis(false),
- _dev("")
-{
-
- dict_t dict = params_to_dict(args);
-
- if (dict.count("master")) {
- _master = boost::lexical_cast< double >( dict["master"]);
- }
-
- std::cerr << args.c_str() << std::endl;
-
- int loglevel = 4;
- if (dict.count("loglevel")) {
- loglevel = boost::lexical_cast< int >( dict["loglevel"] );
- }
-
- bool lmsreset = 0;
- if (dict.count("lmsreset")) {
- lmsreset = boost::lexical_cast< bool >( dict["lmsreset"] );
- }
-
- if (dict.count("txdelay")) {
- _ts += 8192 * boost::lexical_cast< int >( dict["txdelay"] );
- }
-
- if (dict.count("allowdis")) {
- _allow_dis = boost::lexical_cast< bool >( dict["allowdis"] );
- }
-
- if (dict.count("swap_ab")) {
- _swap_ab = true;
- std::cerr << "xtrx_sink_c: swap AB channels";
- }
-
- if (dict.count("swap_iq")) {
- _swap_iq = true;
- std::cerr << "xtrx_sink_c: swap IQ";
- }
-
- if (dict.count("sfl")) {
- _sample_flags = boost::lexical_cast< unsigned >( dict["sfl"] );
- }
-
- if (dict.count("tdd")) {
- _tdd = true;
- std::cerr << "xtrx_sink_c: TDD mode";
- }
-
- if (dict.count("dsp")) {
- _dsp = boost::lexical_cast< double >( dict["dsp"] );
- std::cerr << "xtrx_sink_c: DSP:" << _dsp;
- }
-
- if (dict.count("dev")) {
- _dev = dict["dev"];
- std::cerr << "xtrx_sink_c: XTRX device: %s" << _dev.c_str();
- }
-
- _xtrx = xtrx_obj::get(_dev.c_str(), loglevel, lmsreset);
- if (_xtrx->dev_count() * 2 == _channels) {
- _mimo_mode = true;
- } else if (_xtrx->dev_count() != _channels) {
- throw std::runtime_error("Number of requested channels != number of devices");
- }
- if (dict.count("refclk")) {
- xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["refclk"] ), XTRX_CLKSRC_INT);
- }
- if (dict.count("extclk")) {
- xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["extclk"] ), XTRX_CLKSRC_EXT);
- }
-
- std::cerr << "xtrx_sink_c::xtrx_sink_c()" << std::endl;
- set_alignment(32);
- set_output_multiple(max_burstsz);
-}
-
-xtrx_sink_c::~xtrx_sink_c()
-{
- std::cerr << "xtrx_sink_c::~xtrx_sink_c()" << std::endl;
-}
-
-std::string xtrx_sink_c::name()
-{
- return "GrLibXTRX";
-}
-
-size_t xtrx_sink_c::get_num_channels( void )
-{
- return input_signature()->max_streams();
-}
-
-osmosdr::meta_range_t xtrx_sink_c::get_sample_rates( void )
-{
- osmosdr::meta_range_t range;
- range += osmosdr::range_t( 1000000, 160000000, 1 );
- return range;
-}
-
-double xtrx_sink_c::set_sample_rate( double rate )
-{
- std::cerr << "Set sample rate " << rate << std::endl;
- _rate = _xtrx->set_smaplerate(rate, _master, true, _sample_flags);
- return get_sample_rate();
-}
-
-double xtrx_sink_c::get_sample_rate( void )
-{
- return _rate;
-}
-
-osmosdr::freq_range_t xtrx_sink_c::get_freq_range( size_t chan )
-{
- osmosdr::freq_range_t range;
- range += osmosdr::range_t( double(0.03e9), double(3.8e9), 1); // as far as we know
- return range;
-}
-
-double xtrx_sink_c::set_center_freq( double freq, size_t chan )
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
-
- _freq = freq;
- double corr_freq = (freq)*(1.0 + (_corr) * 0.000001);
-
- std::cerr << "TX Set freq " << freq << std::endl;
- xtrx_channel_t xchan = (xtrx_channel_t)(XTRX_CH_A << chan);
-
- int res = xtrx_tune_ex(_xtrx->dev(), (_tdd) ? XTRX_TUNE_TX_AND_RX_TDD : XTRX_TUNE_TX_FDD, xchan, corr_freq - _dsp, &_freq);
- if (res) {
- std::cerr << "Unable to deliver frequency " << corr_freq << std::endl;
- }
-
- res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_TX, xchan, _dsp, NULL);
- return get_center_freq(chan);
-}
-
-double xtrx_sink_c::get_center_freq( size_t chan )
-{
- return _freq + _dsp;
-}
-
-double xtrx_sink_c::set_freq_corr( double ppm, size_t chan )
-{
- _corr = ppm;
-
- set_center_freq(_freq, chan);
-
- return get_freq_corr( chan );
-}
-
-double xtrx_sink_c::get_freq_corr( size_t chan )
-{
- return _corr;
-}
-
-
-static const std::vector<std::string> s_lna_list = boost::assign::list_of("TX");
-
-std::vector<std::string> xtrx_sink_c::get_gain_names( size_t chan )
-{
- return s_lna_list;
-}
-
-osmosdr::gain_range_t xtrx_sink_c::get_gain_range( size_t chan )
-{
- return get_gain_range("TX", chan);
-}
-
-osmosdr::gain_range_t xtrx_sink_c::get_gain_range( const std::string & name, size_t chan )
-{
- osmosdr::gain_range_t range;
- range += osmosdr::range_t( -31, 0, 1 );
- return range;
-}
-
-bool xtrx_sink_c::set_gain_mode( bool automatic, size_t chan )
-{
- _auto_gain = automatic;
- return get_gain_mode(chan);
-}
-
-bool xtrx_sink_c::get_gain_mode( size_t chan )
-{
- return _auto_gain;
-}
-
-double xtrx_sink_c::set_gain( double gain, size_t chan )
-{
- return set_gain(gain, "TX", chan);
-}
-
-double xtrx_sink_c::set_gain( double igain, const std::string & name, size_t chan )
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
-
- osmosdr::gain_range_t gains = xtrx_sink_c::get_gain_range( name, chan );
- double gain = gains.clip(igain);
- double actual_gain;
-
- std::cerr << "Set TX gain: " << igain << std::endl;
-
- int res = xtrx_set_gain(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
- XTRX_TX_PAD_GAIN, gain, &actual_gain);
- if (res) {
- std::cerr << "Unable to set gain `" << name.c_str() << "`; err=" << res << std::endl;
- }
-
- _gain_tx = actual_gain;
- return actual_gain;
-}
-
-double xtrx_sink_c::get_gain( size_t chan )
-{
- return get_gain("TX");
-}
-
-double xtrx_sink_c::get_gain( const std::string & name, size_t chan )
-{
- return _gain_tx;
-}
-
-double xtrx_sink_c::set_bandwidth( double bandwidth, size_t chan )
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
- std::cerr << "Set bandwidth " << bandwidth << " chan " << chan << std::endl;
-
- if (bandwidth <= 0.0) {
- bandwidth = get_sample_rate() * 0.75;
- if (bandwidth < 0.5e6) {
- bandwidth = 0.5e6;
- }
- }
-
- int res = xtrx_tune_tx_bandwidth(_xtrx->dev(),
- (xtrx_channel_t)(XTRX_CH_A << chan),
- bandwidth, &_bandwidth);
- if (res) {
- std::cerr << "Can't set bandwidth: " << res << std::endl;
- }
- return get_bandwidth(chan);
-}
-
-double xtrx_sink_c::get_bandwidth( size_t chan )
-{
- return _bandwidth;
-}
-
-
-static const std::map<std::string, xtrx_antenna_t> s_ant_map = boost::assign::map_list_of
- ("AUTO", XTRX_TX_AUTO)
- ("B1", XTRX_TX_H)
- ("B2", XTRX_TX_W)
- ("TXH", XTRX_TX_H)
- ("TXW", XTRX_TX_W)
- ;
-static const std::map<xtrx_antenna_t, std::string> s_ant_map_r = boost::assign::map_list_of
- (XTRX_TX_H, "TXH")
- (XTRX_TX_W, "TXW")
- (XTRX_TX_AUTO, "AUTO")
- ;
-
-static xtrx_antenna_t get_ant_type(const std::string& name)
-{
- std::map<std::string, xtrx_antenna_t>::const_iterator it;
-
- it = s_ant_map.find(name);
- if (it != s_ant_map.end()) {
- return it->second;
- }
-
- return XTRX_TX_AUTO;
-}
-
-static const std::vector<std::string> s_ant_list = boost::assign::list_of
- ("AUTO")("TXH")("TXW")
- ;
-
-
-std::vector< std::string > xtrx_sink_c::get_antennas( size_t chan )
-{
- return s_ant_list;
-}
-
-std::string xtrx_sink_c::set_antenna( const std::string & antenna, size_t chan )
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
- _ant = get_ant_type(antenna);
-
- std::cerr << "Set antenna " << antenna << std::endl;
-
- int res = xtrx_set_antenna_ex(_xtrx->dev(),
- (xtrx_channel_t)(XTRX_CH_A << chan),
- _ant);
- if (res) {
- std::cerr << "Can't set antenna: " << antenna << std::endl;
- }
- return get_antenna( chan );
-}
-
-std::string xtrx_sink_c::get_antenna( size_t chan )
-{
- return s_ant_map_r.find(_ant)->second;
-}
-
-void xtrx_sink_c::tag_process(int ninput_items)
-{
- std::sort(_tags.begin(), _tags.end(), gr::tag_t::offset_compare);
-
- const uint64_t samp0_count = this->nitems_read(0);
- uint64_t max_count = samp0_count + ninput_items;
-
- bool found_time_tag = false;
- for (const gr::tag_t &my_tag : _tags) {
- const uint64_t my_tag_count = my_tag.offset;
- const pmt::pmt_t &key = my_tag.key;
- const pmt::pmt_t &value = my_tag.value;
-
- if (my_tag_count >= max_count) {
- break;
- } else if(pmt::equal(key, TIME_KEY)) {
- //if (my_tag_count != samp0_count) {
- // max_count = my_tag_count;
- // break;
- //}
- found_time_tag = true;
- //_metadata.has_time_spec = true;
- //_metadata.time_spec = ::uhd::time_spec_t
- // (pmt::to_uint64(pmt::tuple_ref(value, 0)),
- // pmt::to_double(pmt::tuple_ref(value, 1)));
- uint64_t seconds = pmt::to_uint64(pmt::tuple_ref(value, 0));
- double fractional = pmt::to_double(pmt::tuple_ref(value, 1));
-
- std::cerr << "TX_TIME: " << seconds << ":" << fractional << std::endl;
- }
- } // end for
-
- if (found_time_tag) {
- //_metadata.has_time_spec = true;
- }
-}
-
-int xtrx_sink_c::work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- int ninput_items = noutput_items;
- const uint64_t samp0_count = nitems_read(0);
- get_tags_in_range(_tags, 0, samp0_count, samp0_count + ninput_items);
- if (!_tags.empty())
- tag_process(ninput_items);
-
- xtrx_send_ex_info_t nfo;
- nfo.samples = noutput_items;
- nfo.buffer_count = input_items.size();
- nfo.buffers = &input_items[0];
- nfo.flags = XTRX_TX_DONT_BUFFER;
- if (!_allow_dis)
- nfo.flags |= XTRX_TX_NO_DISCARD;
- nfo.ts = _ts;
- nfo.timeout = 0;
-
- int res = xtrx_send_sync_ex(_xtrx->dev(), &nfo);
- if (res) {
- std::cerr << "Err: " << res << std::endl;
-
- std::stringstream message;
- message << "xtrx_send_burst_sync error: " << -res;
- throw std::runtime_error( message.str() );
- }
-
- _ts += noutput_items;
- for (unsigned i = 0; i < input_items.size(); i++) {
- consume(i, noutput_items);
- }
- return 0;
-}
-
-bool xtrx_sink_c::start()
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
-
- xtrx_run_params_t params;
- xtrx_run_params_init(&params);
-
- params.dir = XTRX_TX;
- if (!_mimo_mode)
- params.tx.flags |= XTRX_RSP_SISO_MODE;
-
- if (_swap_ab)
- params.tx.flags |= XTRX_RSP_SWAP_AB;
-
- if (_swap_iq)
- params.tx.flags |= XTRX_RSP_SWAP_IQ;
-
- params.tx.hfmt = XTRX_IQ_FLOAT32;
- params.tx.wfmt = _otw;
- params.tx.chs = XTRX_CH_AB;
- params.tx.paketsize = 0;
- params.rx_stream_start = 256*1024;
-
- int res = xtrx_run_ex(_xtrx->dev(), &params);
- if (res) {
- std::cerr << "Got error: " << res << std::endl;
- }
-
- return res == 0;
-}
-
-bool xtrx_sink_c::stop()
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
-
- //TODO:
- std::cerr << "xtrx_sink_c::stop()" << std::endl;
- int res = xtrx_stop(_xtrx->dev(), XTRX_TX);
- if (res) {
- std::cerr << "Got error: " << res << std::endl;
- }
-
- return res == 0;
-}
diff --git a/lib/xtrx/xtrx_sink_c.h b/lib/xtrx/xtrx_sink_c.h
deleted file mode 100644
index 1263858..0000000
--- a/lib/xtrx/xtrx_sink_c.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2016 Sergey Kostanabev <sergey.kostanbaev@fairwaves.co>
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef XTRX_SINK_C_H
-#define XTRX_SINK_C_H
-
-#include <gnuradio/block.h>
-#include <gnuradio/sync_block.h>
-
-#include "sink_iface.h"
-#include "xtrx_obj.h"
-
-
-static const pmt::pmt_t SOB_KEY = pmt::string_to_symbol("tx_sob");
-static const pmt::pmt_t EOB_KEY = pmt::string_to_symbol("tx_eob");
-static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("tx_time");
-static const pmt::pmt_t FREQ_KEY = pmt::string_to_symbol("tx_freq");
-static const pmt::pmt_t COMMAND_KEY = pmt::string_to_symbol("tx_command");
-
-class xtrx_sink_c;
-
-typedef boost::shared_ptr< xtrx_sink_c > xtrx_sink_c_sptr;
-
-xtrx_sink_c_sptr make_xtrx_sink_c( const std::string & args = "" );
-
-class xtrx_sink_c :
- public gr::sync_block,
- public sink_iface
-{
-private:
- friend xtrx_sink_c_sptr make_xtrx_sink_c(const std::string &args);
-
- xtrx_sink_c(const std::string &args);
-
-public:
- ~xtrx_sink_c();
-
- std::string name();
-
- static std::vector< std::string > get_devices( bool fake = false ) { return xtrx_obj::get_devices(); }
-
- size_t get_num_channels( void );
-
- osmosdr::meta_range_t get_sample_rates( void );
- double set_sample_rate( double rate );
- double get_sample_rate( void );
-
- osmosdr::freq_range_t get_freq_range( size_t chan = 0 );
- double set_center_freq( double freq, size_t chan = 0 );
- double get_center_freq( size_t chan = 0 );
- double set_freq_corr( double ppm, size_t chan = 0 );
- double get_freq_corr( size_t chan = 0 );
-
- std::vector<std::string> get_gain_names( size_t chan = 0 );
- osmosdr::gain_range_t get_gain_range( size_t chan = 0 );
- osmosdr::gain_range_t get_gain_range( const std::string & name, size_t chan = 0 );
- bool set_gain_mode( bool automatic, size_t chan = 0 );
- bool get_gain_mode( size_t chan = 0 );
- double set_gain( double gain, size_t chan = 0 );
- double set_gain( double gain, const std::string & name, size_t chan = 0 );
- double get_gain( size_t chan = 0 );
- double get_gain( const std::string & name, size_t chan = 0 );
-
- std::vector< std::string > get_antennas( size_t chan = 0 );
- std::string set_antenna( const std::string & antenna, size_t chan = 0 );
- std::string get_antenna( size_t chan = 0 );
-
- double set_bandwidth( double bandwidth, size_t chan = 0 );
- double get_bandwidth( size_t chan = 0 );
-
- int work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- bool start();
- bool stop();
-
- void tag_process(int ninput_items);
-
-private:
- xtrx_obj_sptr _xtrx;
- std::vector<gr::tag_t> _tags;
-
- unsigned _sample_flags;
- double _rate;
- double _master;
- double _freq;
- double _corr;
- double _bandwidth;
- double _dsp;
- bool _auto_gain;
-
- xtrx_wire_format_t _otw;
- bool _mimo_mode;
-
- int _gain_tx;
-
- unsigned _channels;
- xtrx_antenna_t _ant;
-
- uint64_t _ts;
-
- bool _swap_ab;
- bool _swap_iq;
-
- bool _tdd;
- bool _allow_dis;
-
- std::string _dev;
-};
-
-#endif // xtrx_sink_c_H
diff --git a/lib/xtrx/xtrx_source_c.cc b/lib/xtrx/xtrx_source_c.cc
deleted file mode 100644
index 4fdc877..0000000
--- a/lib/xtrx/xtrx_source_c.cc
+++ /dev/null
@@ -1,583 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2016,2017 Sergey Kostanbaev <sergey.kostanbaev@fairwaves.co>
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-#include <fstream>
-#include <string>
-#include <sstream>
-#include <map>
-
-#include <boost/assign.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/thread.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/thread/mutex.hpp>
-
-#include <gnuradio/io_signature.h>
-#include <gnuradio/blocks/deinterleave.h>
-#include <gnuradio/blocks/float_to_complex.h>
-
-#include "xtrx_source_c.h"
-
-#include "arg_helpers.h"
-
-using namespace boost::assign;
-
-
-xtrx_source_c_sptr make_xtrx_source_c(const std::string &args)
-{
- return gnuradio::get_initial_sptr(new xtrx_source_c(args));
-}
-
-static size_t parse_nchan(const std::string &args)
-{
- size_t nchan = 1;
-
- dict_t dict = params_to_dict(args);
-
- if (dict.count("nchan"))
- nchan = boost::lexical_cast< size_t >( dict["nchan"] );
-
- if (nchan < 1)
- nchan = 1;
-
- return nchan;
-}
-
-xtrx_source_c::xtrx_source_c(const std::string &args) :
- gr::sync_block("xtrx_source_c",
- gr::io_signature::make(0, 0, 0),
- gr::io_signature::make(parse_nchan(args),
- parse_nchan(args),
- sizeof(gr_complex))),
- _sample_flags(0),
- _rate(0),
- _master(0),
- _freq(0),
- _corr(0),
- _bandwidth(0),
- _auto_gain(false),
- _otw(XTRX_WF_16),
- _mimo_mode(false),
- _gain_lna(0),
- _gain_tia(0),
- _gain_pga(0),
- _channels(parse_nchan(args)),
- _swap_ab(false),
- _swap_iq(false),
- _loopback(false),
- _tdd(false),
- _fbctrl(false),
- _timekey(false),
- _dsp(0)
-{
- _id = pmt::string_to_symbol(args);
-
- dict_t dict = params_to_dict(args);
-
- if (dict.count("otw_format")) {
- const std::string& otw = dict["otw_format"];
- if (otw == "sc16" || otw == "16") {
- _otw = XTRX_WF_16;
- } else if (otw == "sc12" || otw == "12") {
- _otw = XTRX_WF_12;
- } else if (otw == "sc8" || otw == "8") {
- _otw = XTRX_WF_8;
- } else {
- throw std::runtime_error("Parameter `otw_format` should be {sc16,sc12,sc8}");
- }
- }
-
- if (dict.count("master")) {
- _master = boost::lexical_cast< double >( dict["master"]);
- }
-
- std::cerr << args.c_str() << std::endl;
-
- int loglevel = 4;
- if (dict.count("loglevel")) {
- loglevel = boost::lexical_cast< int >( dict["loglevel"] );
- }
-
- bool lmsreset = 0;
- if (dict.count("lmsreset")) {
- lmsreset = boost::lexical_cast< bool >( dict["lmsreset"] );
- }
-
- if (dict.count("fbctrl")) {
- _fbctrl = boost::lexical_cast< bool >( dict["fbctrl"] );
- }
-
- if (dict.count("swap_ab")) {
- _swap_ab = true;
- std::cerr << "xtrx_source_c: swap AB channels";
- }
-
- if (dict.count("swap_iq")) {
- _swap_iq = true;
- std::cerr << "xtrx_source_c: swap IQ";
- }
-
- if (dict.count("sfl")) {
- _sample_flags = boost::lexical_cast< unsigned >( dict["sfl"] );
- }
-
- if (dict.count("loopback")) {
- _loopback = true;
- std::cerr << "xtrx_source_c: loopback";
- }
-
- if (dict.count("tdd")) {
- _tdd = true;
- std::cerr << "xtrx_source_c: TDD mode";
- }
-
- if (dict.count("dsp")) {
- _dsp = boost::lexical_cast< double >( dict["dsp"] );
- std::cerr << "xtrx_source_c: DSP:" << _dsp;
- }
-
- if (dict.count("dev")) {
- _dev = dict["dev"];
- std::cerr << "xtrx_source_c: XTRX device: %s" << _dev.c_str();
- }
-
- _xtrx = xtrx_obj::get(_dev.c_str(), loglevel, lmsreset);
- if (_xtrx->dev_count() * 2 == _channels) {
- _mimo_mode = true;
- } else if (_xtrx->dev_count() != _channels) {
- throw std::runtime_error("Number of requested channels != number of devices");
- }
-
- if (dict.count("refclk")) {
- xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["refclk"] ), XTRX_CLKSRC_INT);
- }
- if (dict.count("extclk")) {
- xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["extclk"] ), XTRX_CLKSRC_EXT);
- }
-
- if (dict.count("vio")) {
- unsigned vio = boost::lexical_cast< unsigned >( dict["vio"] );
- _xtrx->set_vio(vio);
- }
-
- if (dict.count("dac")) {
- unsigned dac = boost::lexical_cast< unsigned >( dict["dac"] );
- xtrx_val_set(_xtrx->dev(), XTRX_TRX, XTRX_CH_ALL, XTRX_VCTCXO_DAC_VAL, dac);
- }
-
- if (dict.count("pmode")) {
- unsigned pmode = boost::lexical_cast< unsigned >( dict["pmode"] );
- xtrx_val_set(_xtrx->dev(), XTRX_TRX, XTRX_CH_ALL, XTRX_LMS7_PWR_MODE, pmode);
- }
-
- if (dict.count("timekey")) {
- _timekey = boost::lexical_cast< bool >( dict["timekey"] );
- }
-
- std::cerr << "xtrx_source_c::xtrx_source_c()" << std::endl;
- set_alignment(32);
- if (_otw == XTRX_WF_16) {
- if (_mimo_mode)
- set_output_multiple(4096);
- else
- set_output_multiple(8192);
- } else if (_otw == XTRX_WF_8) {
- if (_mimo_mode)
- set_output_multiple(8192);
- else
- set_output_multiple(16384);
- }
-}
-
-xtrx_source_c::~xtrx_source_c()
-{
- std::cerr << "xtrx_source_c::~xtrx_source_c()" << std::endl;
-}
-
-std::string xtrx_source_c::name()
-{
- return "GrLibXTRX";
-}
-
-size_t xtrx_source_c::get_num_channels( void )
-{
- return output_signature()->max_streams();
-}
-
-osmosdr::meta_range_t xtrx_source_c::get_sample_rates( void )
-{
- osmosdr::meta_range_t range;
- range += osmosdr::range_t( 200000, 160000000, 1 );
- return range;
-}
-
-double xtrx_source_c::set_sample_rate( double rate )
-{
- std::cerr << "Set sample rate " << rate << std::endl;
- _rate = _xtrx->set_smaplerate(rate, _master, false, _sample_flags);
- return get_sample_rate();
-}
-
-double xtrx_source_c::get_sample_rate( void )
-{
- return _rate;
-}
-
-osmosdr::freq_range_t xtrx_source_c::get_freq_range( size_t chan )
-{
- osmosdr::freq_range_t range;
- range += osmosdr::range_t( double(0.03e9), double(3.8e9), 1); // as far as we know
- return range;
-}
-
-double xtrx_source_c::set_center_freq( double freq, size_t chan )
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
-
- _freq = freq;
- double corr_freq = (freq)*(1.0 + (_corr) * 0.000001);
-
- if (_tdd)
- return get_center_freq(chan);
-
- xtrx_channel_t xchan = (xtrx_channel_t)(XTRX_CH_A << chan);
-
- std::cerr << "Set freq " << freq << std::endl;
-
- int res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_RX_FDD, xchan, corr_freq - _dsp, &_freq);
- if (res) {
- std::cerr << "Unable to deliver frequency " << corr_freq << std::endl;
- }
-
- res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_RX, xchan, _dsp, NULL);
-
- return get_center_freq(chan);
-}
-
-double xtrx_source_c::get_center_freq( size_t chan )
-{
- return _freq;
-}
-
-double xtrx_source_c::set_freq_corr( double ppm, size_t chan )
-{
- _corr = ppm;
-
- set_center_freq(_freq, chan);
-
- return get_freq_corr( chan );
-}
-
-double xtrx_source_c::get_freq_corr( size_t chan )
-{
- return _corr;
-}
-
-static const std::map<std::string, xtrx_gain_type_t> s_lna_map = boost::assign::map_list_of
- ("LNA", XTRX_RX_LNA_GAIN)
- ("TIA", XTRX_RX_TIA_GAIN)
- ("PGA", XTRX_RX_PGA_GAIN)
- ("LB", XTRX_RX_LB_GAIN)
- ;
-
-static xtrx_gain_type_t get_gain_type(const std::string& name)
-{
- std::map<std::string, xtrx_gain_type_t>::const_iterator it;
-
- it = s_lna_map.find(name);
- if (it != s_lna_map.end()) {
- return it->second;
- }
-
- return XTRX_RX_LNA_GAIN;
-}
-
-static const std::vector<std::string> s_lna_list = boost::assign::list_of
- ("LNA")("TIA")("PGA")("LB")
- ;
-
-std::vector<std::string> xtrx_source_c::get_gain_names( size_t chan )
-{
- return s_lna_list;
-}
-
-osmosdr::gain_range_t xtrx_source_c::get_gain_range( size_t chan )
-{
- return get_gain_range("LNA", chan);
-}
-
-osmosdr::gain_range_t xtrx_source_c::get_gain_range( const std::string & name, size_t chan )
-{
- osmosdr::gain_range_t range;
-
- if (name == "LNA") {
- range += osmosdr::range_t( 0, 24, 3 );
- range += osmosdr::range_t( 25, 30, 1 );
- } else if (name == "TIA") {
- range += osmosdr::range_t( 0 );
- range += osmosdr::range_t( 9 );
- range += osmosdr::range_t( 12 );
- } else if (name == "PGA") {
- range += osmosdr::range_t( -12.5, 12.5, 1 );
- } else if (name == "LB") {
- range += osmosdr::range_t( -40, 0, 1 );
- }
-
- return range;
-}
-
-bool xtrx_source_c::set_gain_mode( bool automatic, size_t chan )
-{
- _auto_gain = automatic;
- return get_gain_mode(chan);
-}
-
-bool xtrx_source_c::get_gain_mode( size_t chan )
-{
- return _auto_gain;
-}
-
-double xtrx_source_c::set_gain( double gain, size_t chan )
-{
- return set_gain(gain, "LNA", chan);
-}
-
-double xtrx_source_c::set_gain( double igain, const std::string & name, size_t chan )
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
-
- osmosdr::gain_range_t gains = xtrx_source_c::get_gain_range( name, chan );
- double gain = gains.clip(igain);
- double actual_gain;
- xtrx_gain_type_t gt = get_gain_type(name);
-
- std::cerr << "Set gain " << name << " (" << gt << "): " << igain << std::endl;
-
- int res = xtrx_set_gain(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
- gt, gain, &actual_gain);
- if (res) {
- std::cerr << "Unable to set gain `" << name.c_str() << "`; err=" << res << std::endl;
- }
-
- switch (gt) {
- case XTRX_RX_LNA_GAIN: _gain_lna = actual_gain; break;
- case XTRX_RX_TIA_GAIN: _gain_tia = actual_gain; break;
- case XTRX_RX_PGA_GAIN: _gain_pga = actual_gain; break;
- default: break;
- }
-
- return actual_gain;
-}
-
-double xtrx_source_c::get_gain( size_t chan )
-{
- return get_gain("LNA");
-}
-
-double xtrx_source_c::get_gain( const std::string & name, size_t chan )
-{
- xtrx_gain_type_t gt = get_gain_type(name);
- switch (gt) {
- case XTRX_RX_LNA_GAIN: return _gain_lna;
- case XTRX_RX_TIA_GAIN: return _gain_tia;
- case XTRX_RX_PGA_GAIN: return _gain_pga;
- default: return 0;
- }
-}
-
-double xtrx_source_c::set_if_gain(double gain, size_t chan)
-{
- return set_gain(gain, "PGA", chan);
-}
-
-double xtrx_source_c::set_bandwidth( double bandwidth, size_t chan )
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
- std::cerr << "Set bandwidth " << bandwidth << " chan " << chan << std::endl;
-
- if (bandwidth <= 0.0) {
- bandwidth = get_sample_rate() * 0.75;
- if (bandwidth < 0.5e6) {
- bandwidth = 0.5e6;
- }
- }
-
- int res = xtrx_tune_rx_bandwidth(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
- bandwidth, &_bandwidth);
- if (res) {
- std::cerr << "Can't set bandwidth: " << res << std::endl;
- }
- return get_bandwidth(chan);
-}
-
-double xtrx_source_c::get_bandwidth( size_t chan )
-{
- return _bandwidth;
-}
-
-osmosdr::freq_range_t xtrx_source_c::get_bandwidth_range( size_t chan )
-{
- return osmosdr::freq_range_t(500e3, 140e6, 0);
-}
-
-
-static const std::map<std::string, xtrx_antenna_t> s_ant_map = boost::assign::map_list_of
- ("AUTO", XTRX_RX_AUTO)
- ("RXL", XTRX_RX_L)
- ("RXH", XTRX_RX_H)
- ("RXW", XTRX_RX_W)
- ("RXL_LB", XTRX_RX_L_LB)
- ("RXW_LB", XTRX_RX_W_LB)
- ;
-static const std::map<xtrx_antenna_t, std::string> s_ant_map_r = boost::assign::map_list_of
- (XTRX_RX_AUTO, "AUTO")
- (XTRX_RX_L, "RXL")
- (XTRX_RX_H, "RXH")
- (XTRX_RX_W, "RXW")
- (XTRX_RX_L_LB, "RXL_LB")
- (XTRX_RX_W_LB, "RXW_LB")
- ;
-
-static xtrx_antenna_t get_ant_type(const std::string& name)
-{
- std::map<std::string, xtrx_antenna_t>::const_iterator it;
-
- it = s_ant_map.find(name);
- if (it != s_ant_map.end()) {
- return it->second;
- }
-
- return XTRX_RX_AUTO;
-}
-
-static const std::vector<std::string> s_ant_list = boost::assign::list_of
- ("AUTO")("RXL")("RXH")("RXW")
- ;
-
-
-std::vector< std::string > xtrx_source_c::get_antennas( size_t chan )
-{
- return s_ant_list;
-}
-
-std::string xtrx_source_c::set_antenna( const std::string & antenna, size_t chan )
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
- _ant = get_ant_type(antenna);
-
- std::cerr << "Set antenna " << antenna << " type:" << _ant << std::endl;
-
- int res = xtrx_set_antenna_ex(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
- _ant);
- if (res) {
- std::cerr << "Can't set antenna: " << antenna << std::endl;
- }
- return get_antenna( chan );
-}
-
-std::string xtrx_source_c::get_antenna( size_t chan )
-{
- return s_ant_map_r.find(_ant)->second;
-}
-
-int xtrx_source_c::work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- xtrx_recv_ex_info_t ri;
- ri.samples = noutput_items;
- ri.buffer_count = output_items.size();
- ri.buffers = &output_items[0];
- ri.flags = RCVEX_DONT_INSER_ZEROS | RCVEX_DROP_OLD_ON_OVERFLOW;
- ri.timeout = 1000;
-
- int res = xtrx_recv_sync_ex(_xtrx->dev(), &ri);
- if (res) {
- std::stringstream message;
- message << "xtrx_recv_sync error: " << -res;
- throw std::runtime_error( message.str() );
- }
-
- if (_timekey) {
- uint64_t seconds = (ri.out_first_sample / _rate);
- double fractional = (ri.out_first_sample - (uint64_t)(_rate * seconds)) / _rate;
-
- //std::cerr << "Time " << seconds << ":" << fractional << std::endl;
- const pmt::pmt_t val = pmt::make_tuple
- (pmt::from_uint64(seconds),
- pmt::from_double(fractional));
- for(size_t i = 0; i < output_items.size(); i++) {
- this->add_item_tag(i, nitems_written(0), TIME_KEY,
- val, _id);
- this->add_item_tag(i, nitems_written(0), RATE_KEY,
- pmt::from_double(_rate), _id);
- this->add_item_tag(i, nitems_written(0), FREQ_KEY,
- pmt::from_double(this->get_center_freq(i)), _id);
- }
- }
- return ri.out_samples;
-}
-
-bool xtrx_source_c::start()
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
-
- xtrx_run_params_t params;
- xtrx_run_params_init(&params);
-
- params.dir = XTRX_RX;
- if (!_mimo_mode)
- params.rx.flags |= XTRX_RSP_SISO_MODE;
-
- if (_swap_ab)
- params.rx.flags |= XTRX_RSP_SWAP_AB;
-
- if (_swap_iq)
- params.rx.flags |= XTRX_RSP_SWAP_IQ;
-
- params.rx.hfmt = XTRX_IQ_FLOAT32;
- params.rx.wfmt = _otw;
- params.rx.chs = XTRX_CH_AB;
- params.rx.paketsize = 0;
- params.rx_stream_start = 256*1024;
-
- params.nflags = (_loopback) ? XTRX_RUN_DIGLOOPBACK : 0;
-
- int res = xtrx_run_ex(_xtrx->dev(), &params);
- if (res) {
- std::cerr << "Got error: " << res << std::endl;
- }
-
- res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_RX, XTRX_CH_ALL, _dsp, NULL);
-
- return res == 0;
-}
-
-bool xtrx_source_c::stop()
-{
- boost::mutex::scoped_lock lock(_xtrx->mtx);
- //TODO:
- std::cerr << "xtrx_source_c::stop()" << std::endl;
- int res = xtrx_stop(_xtrx->dev(), XTRX_RX);
- if (res) {
- std::cerr << "Got error: " << res << std::endl;
- }
-
- return res == 0;
-}
diff --git a/lib/xtrx/xtrx_source_c.h b/lib/xtrx/xtrx_source_c.h
deleted file mode 100644
index fda9d77..0000000
--- a/lib/xtrx/xtrx_source_c.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2016,2017 Sergey Kostanbaev <sergey.kostanbaev@fairwaves.co>
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-#ifndef XTRX_SOURCE_C_H
-#define XTRX_SOURCE_C_H
-
-#include <gnuradio/block.h>
-#include <gnuradio/sync_block.h>
-
-#include "source_iface.h"
-#include "xtrx_obj.h"
-
-static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("rx_time");
-static const pmt::pmt_t RATE_KEY = pmt::string_to_symbol("rx_rate");
-static const pmt::pmt_t FREQ_KEY = pmt::string_to_symbol("rx_freq");
-
-class xtrx_source_c;
-
-typedef boost::shared_ptr< xtrx_source_c > xtrx_source_c_sptr;
-
-xtrx_source_c_sptr make_xtrx_source_c( const std::string & args = "" );
-
-class xtrx_source_c :
- public gr::sync_block,
- public source_iface
-{
-private:
- friend xtrx_source_c_sptr make_xtrx_source_c(const std::string &args);
-
- xtrx_source_c(const std::string &args);
-
-public:
- ~xtrx_source_c();
-
- std::string name();
-
- static std::vector< std::string > get_devices( bool fake = false ) { return xtrx_obj::get_devices(); }
-
- size_t get_num_channels( void );
-
- osmosdr::meta_range_t get_sample_rates( void );
- double set_sample_rate( double rate );
- double get_sample_rate( void );
-
- osmosdr::freq_range_t get_freq_range( size_t chan = 0 );
- double set_center_freq( double freq, size_t chan = 0 );
- double get_center_freq( size_t chan = 0 );
- double set_freq_corr( double ppm, size_t chan = 0 );
- double get_freq_corr( size_t chan = 0 );
-
- std::vector<std::string> get_gain_names( size_t chan = 0 );
- osmosdr::gain_range_t get_gain_range( size_t chan = 0 );
- osmosdr::gain_range_t get_gain_range( const std::string & name, size_t chan = 0 );
- bool set_gain_mode( bool automatic, size_t chan = 0 );
- bool get_gain_mode( size_t chan = 0 );
- double set_gain( double gain, size_t chan = 0 );
- double set_gain( double gain, const std::string & name, size_t chan = 0 );
- double get_gain( size_t chan = 0 );
- double get_gain( const std::string & name, size_t chan = 0 );
-
- double set_if_gain( double gain, size_t chan = 0 );
-
- std::vector< std::string > get_antennas( size_t chan = 0 );
- std::string set_antenna( const std::string & antenna, size_t chan = 0 );
- std::string get_antenna( size_t chan = 0 );
-
- double set_bandwidth( double bandwidth, size_t chan = 0 );
- double get_bandwidth( size_t chan = 0 );
- osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0);
-
- int work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- bool start();
- bool stop();
-
-private:
- xtrx_obj_sptr _xtrx;
- pmt::pmt_t _id;
-
- unsigned _sample_flags;
- double _rate;
- double _master;
- double _freq;
- double _corr;
- double _bandwidth;
- bool _auto_gain;
-
- xtrx_wire_format_t _otw;
- bool _mimo_mode;
-
- int _gain_lna;
- int _gain_tia;
- int _gain_pga;
-
- unsigned _channels;
- xtrx_antenna_t _ant;
-
- bool _swap_ab;
- bool _swap_iq;
- bool _loopback;
- bool _tdd;
- bool _fbctrl;
- bool _timekey;
-
- double _dsp;
- std::string _dev;
-};
-
-#endif // XTRX_SOURCE_C_H
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 53cb61e..8841f36 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -1,19 +1,19 @@
# Copyright 2011 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
diff --git a/python/__init__.py b/python/__init__.py
index 1cb090f..70c469d 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -22,4 +22,15 @@
This is the GNU Radio OsmoSDR module.
'''
-from .osmosdr_swig import *
+from __future__ import unicode_literals
+
+# import swig generated symbols into the osmosdr namespace
+try:
+ # this might fail if the module is python-only
+ from .osmosdr_swig import *
+except ImportError as ie:
+ print(ie)
+ pass
+
+# import any pure python here
+#
diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt
index 159f212..d01d029 100644
--- a/swig/CMakeLists.txt
+++ b/swig/CMakeLists.txt
@@ -1,27 +1,35 @@
# Copyright 2011 Free Software Foundation, Inc.
#
-# This file is part of gr-osmosdr
+# This file is part of GNU Radio
#
-# gr-osmosdr is free software; you can redistribute it and/or modify
+# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
-# gr-osmosdr is distributed in the hope that it will be useful,
+# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with gr-osmosdr; see the file COPYING. If not, write to
+# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
########################################################################
+# Check if there is C++ code at all
+########################################################################
+#if(NOT osmosdr_sources)
+# MESSAGE(STATUS "No C++ sources... skipping swig/")
+# return()
+#endif(NOT osmosdr_sources)
+
+########################################################################
# Include swig generation macros
########################################################################
find_package(SWIG)
-find_package(PythonLibs 3)
+find_package(PythonLibs)
if(NOT SWIG_FOUND OR NOT PYTHONLIBS_FOUND)
return()
endif()
@@ -31,13 +39,16 @@ include(GrPython)
########################################################################
# Setup swig generation
########################################################################
+foreach(incdir ${GNURADIO_ALL_INCLUDE_DIRS})
+ list(APPEND GR_SWIG_INCLUDE_DIRS ${incdir}/gnuradio/swig)
+endforeach(incdir)
set(GR_SWIG_INCLUDE_DIRS $<TARGET_PROPERTY:gnuradio::runtime_swig,INTERFACE_INCLUDE_DIRECTORIES>)
set(GR_SWIG_TARGET_DEPS gnuradio::runtime_swig)
set(GR_SWIG_LIBRARIES gnuradio-osmosdr)
set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/osmosdr_swig_doc.i)
-set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include/osmosdr)
+set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include)
GR_SWIG_MAKE(osmosdr_swig osmosdr_swig.i)