diff options
Diffstat (limited to 'lib')
63 files changed, 2841 insertions, 3319 deletions
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 ¶ms ) 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 ¶ms ) 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(¶ms); - - 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(), ¶ms); - 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(¶ms); - - 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(), ¶ms); - 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 |