--- CMakeLists.txt.orig +++ CMakeLists.txt @@ -183,6 +183,7 @@ find_package(LibFreeSRP) find_package(LibXTRX) find_package(Doxygen) +find_package(GNURadioIIO) # Python ########## --- /dev/null +++ cmake/Modules/FindGNURadioIIO.cmake @@ -0,0 +1,34 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_GNURADIO_IIO gnuradio-iio) + +FIND_PATH( + GNURADIO_IIO_INCLUDE_DIRS + NAMES iio/api.h + HINTS $ENV{GNURADIO_IIO_DIR}/include + ${PC_GNURADIO_IIO_INCLUDEDIR} + PATHS /usr/local/include + /usr/include +) + +FIND_LIBRARY( + GNURADIO_IIO_LIBRARIES + NAMES gnuradio-iio + HINTS $ENV{GNURADIO_IIO_DIR}/lib + ${PC_GNURADIO_IIO_LIBDIR} + PATHS /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 +) + +if(GNURADIO_IIO_INCLUDE_DIRS AND GNURADIO_IIO_LIBRARIES) + set(GNURADIO_IIO_FOUND TRUE CACHE INTERNAL "gnuradio-iio found") + message(STATUS "Found gnuradio-iio: ${GNURADIO_IIO_INCLUDE_DIRS}, ${GNURADIO_IIO_LIBRARIES}") +else(GNURADIO_IIO_INCLUDE_DIRS AND GNURADIO_IIO_LIBRARIES) + set(GNURADIO_IIO_FOUND FALSE CACHE INTERNAL "gnuradio-iio found") + message(STATUS "gnuradio-iio not found.") +endif(GNURADIO_IIO_INCLUDE_DIRS AND GNURADIO_IIO_LIBRARIES) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_IIO DEFAULT_MSG GNURADIO_IIO_LIBRARIES GNURADIO_IIO_INCLUDE_DIRS) +MARK_AS_ADVANCED(GNURADIO_IIO_LIBRARIES GNURADIO_IIO_INCLUDE_DIRS) --- /dev/null +++ cmake/Modules/FindIIO.cmake @@ -0,0 +1,28 @@ +######################################################################## +# Find the IIO userspace library +######################################################################## + +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_IIO iio) + +FIND_PATH( + IIO_INCLUDE_DIRS + NAMES iio.h + HINTS $ENV{IIO_DIR}/include + ${PC_IIO_INCLUDEDIR} + PATHS /usr/local/include + /usr/include +) + +FIND_LIBRARY( + IIO_LIBRARIES + NAMES iio + HINTS $ENV{IIO_DIR}/lib + ${PC_IIO_LIBDIR} + PATHS /usr/local/lib + /usr/lib +) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(IIO DEFAULT_MSG IIO_LIBRARIES IIO_INCLUDE_DIRS) +MARK_AS_ADVANCED(IIO_LIBRARIES IIO_INCLUDE_DIRS) --- lib/CMakeLists.txt.orig +++ lib/CMakeLists.txt @@ -167,6 +167,14 @@ add_subdirectory(rtl_tcp) endif(ENABLE_RTL_TCP) +######################################################################## +# Setup IIO component +######################################################################## +GR_REGISTER_COMPONENT("IIO Devices (like PlutoSDR)" ENABLE_IIO GNURADIO_IIO_FOUND) +if(ENABLE_IIO) + add_subdirectory(plutosdr) +endif(ENABLE_IIO) + ######################################################################## # Setup UHD component ######################################################################## --- lib/config.h.in.orig +++ lib/config.h.in @@ -20,6 +20,7 @@ #cmakedefine ENABLE_REDPITAYA #cmakedefine ENABLE_FREESRP #cmakedefine ENABLE_XTRX +#cmakedefine ENABLE_IIO //provide NAN define for MSVC older than VC12 #if defined(_MSC_VER) && (_MSC_VER < 1800) --- lib/device.cc.orig +++ lib/device.cc @@ -89,6 +89,10 @@ #include #endif +#ifdef ENABLE_IIO +#include +#endif + #include "arg_helpers.h" using namespace osmosdr; @@ -193,6 +197,10 @@ for (std::string dev : soapy_source_c::get_devices()) devices.push_back( device_t(dev) ); #endif +#ifdef ENABLE_IIO + for (std::string dev : plutosdr_source_c::get_devices()) + devices.push_back( device_t(dev) ); +#endif /* software-only sources should be appended at the very end, * hopefully resulting in hardware sources to be shown first --- /dev/null +++ lib/plutosdr/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright 2012 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +target_include_directories(gnuradio-osmosdr PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${GNURADIO_IIO_INCLUDE_DIRS} + ${IIO_INCLUDE_DIRS} +) + +target_link_libraries(gnuradio-osmosdr + ${GNURADIO_IIO_LIBRARIES} + ${IIO_LIBRARIES} +) + +list(APPEND gr_osmosdr_srcs + ${CMAKE_CURRENT_SOURCE_DIR}/plutosdr_source_c.cc +) +set(gr_osmosdr_srcs ${gr_osmosdr_srcs} PARENT_SCOPE) --- /dev/null +++ lib/plutosdr/plutosdr_source_c.cc @@ -0,0 +1,262 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Dimitri Stolnikov + * + * 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 +#include + +#include "arg_helpers.h" +#include "osmosdr/source.h" +#include "plutosdr_source_c.h" + +using namespace boost::assign; + +plutosdr_source_c_sptr make_plutosdr_source_c(const std::string &args) +{ + return gnuradio::get_initial_sptr(new plutosdr_source_c(args)); +} + +plutosdr_source_c::plutosdr_source_c(const std::string &args) : + gr::hier_block2("plutosdr_source_c", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(1, 1, sizeof(gr_complex))) +{ + uri = "ip:pluto.local"; + frequency = 434000000; + samplerate = 2500000; + decimation = 0; + bandwidth = 2000000; + buffer_size = 0x4000; + quadrature = true; + rfdc = true; + bbdc = true; + gain_auto = false; + gain_value = 50; + filter = ""; + filter_auto = true; + _freq_corr = 0.0; + + dict_t dict = params_to_dict(args); + if (dict.count("uri")) + uri = boost::lexical_cast< std::string >( dict["uri"] ); + + std::cerr << "Using PlutoSDR URI = " << uri << std::endl; + + _src = gr::iio::pluto_source::make(uri, frequency, samplerate, + bandwidth, buffer_size, + quadrature, rfdc, bbdc, + "manual", gain_value, + filter.c_str(), filter_auto); + + connect( _src, 0, self(), 0 ); +} + +plutosdr_source_c::~plutosdr_source_c() +{ +} + +std::vector< std::string > plutosdr_source_c::get_devices() +{ + std::vector< std::string > devices; + + std::string args = "plutosdr,label='PlutoSDR'"; + + devices.push_back( args ); + + return devices; +} + +std::string plutosdr_source_c::name() +{ + return "PlutoSDR"; +} + +size_t plutosdr_source_c::get_num_channels() +{ + return output_signature()->max_streams(); +} + +osmosdr::meta_range_t plutosdr_source_c::get_sample_rates( void ) +{ + osmosdr::meta_range_t rates; + + rates += osmosdr::range_t( 2500000 ); + rates += osmosdr::range_t( 5000000 ); + rates += osmosdr::range_t( 10000000 ); + rates += osmosdr::range_t( 20000000 ); + + return rates; +} + +double plutosdr_source_c::set_sample_rate( double rate ) +{ + samplerate = (unsigned long) rate; + set_params(); + + return samplerate; +} + +double plutosdr_source_c::get_sample_rate( void ) +{ + return samplerate; +} + +osmosdr::freq_range_t plutosdr_source_c::get_freq_range( size_t chan ) +{ + osmosdr::freq_range_t range; + + range += osmosdr::range_t( 70.0e6, 6000.0e6, 1.0 ); + + return range; +} + +double plutosdr_source_c::set_center_freq( double freq, size_t chan ) +{ + frequency = (unsigned long long) freq; + set_params(); + + return freq; +} + +double plutosdr_source_c::get_center_freq( size_t chan ) +{ + return frequency; +} + +double plutosdr_source_c::set_freq_corr( double ppm, size_t chan) +{ + _freq_corr = ppm; + set_params(); + + return ppm; +} + +double plutosdr_source_c::get_freq_corr( size_t chan) +{ + return _freq_corr; +} + +std::vector plutosdr_source_c::get_gain_names( size_t chan ) +{ + std::vector< std::string > gains; + + gains.push_back( "RF" ); + + return gains; +} + +osmosdr::gain_range_t plutosdr_source_c::get_gain_range( size_t chan) +{ + osmosdr::gain_range_t range; + range += osmosdr::range_t( -10, 77, 1 ); // https://wiki.analog.com/resources/tools-software/linux-drivers/iio-transceiver/ad9361#rx_gain_control + + return range; +} + +osmosdr::gain_range_t plutosdr_source_c::get_gain_range( const std::string & name, + size_t chan) +{ + osmosdr::gain_range_t range; + + range += osmosdr::range_t( -10, 77, 1 ); + + return range; +} + +bool plutosdr_source_c::set_gain_mode( bool automatic, size_t chan ) +{ + gain_auto = automatic; + set_params(); + + return automatic; +} + +bool plutosdr_source_c::get_gain_mode( size_t chan ) +{ + return gain_auto; +} + +double plutosdr_source_c::set_gain( double gain, size_t chan ) +{ + gain_value = gain; + set_params(); + + return gain; +} + +double plutosdr_source_c::set_gain( double gain, const std::string & name, size_t chan ) +{ + gain_value = gain; + set_params(); + + return gain; +} + +double plutosdr_source_c::get_gain( size_t chan ) +{ + return gain_value; +} + +double plutosdr_source_c::get_gain( const std::string & name, size_t chan ) +{ + return gain_value; +} + +std::vector< std::string > plutosdr_source_c::get_antennas( size_t chan ) +{ + std::vector< std::string > antennas; + + antennas += get_antenna( chan ); + + return antennas; +} + +std::string plutosdr_source_c::set_antenna( const std::string & antenna, size_t chan ) +{ + return get_antenna( chan ); +} + +std::string plutosdr_source_c::get_antenna( size_t chan ) +{ + return "A_BALANCED"; +} + +double plutosdr_source_c::set_bandwidth( double bw, size_t chan ) +{ + if (bw == 0.0) + bw = 0.8 * samplerate; // auto bandwidth + + bandwidth = (unsigned long)bw; + set_params(); + return bandwidth; +} + +double plutosdr_source_c::get_bandwidth( size_t chan ) +{ + return bandwidth; +} + +void plutosdr_source_c::set_params( void ) +{ + unsigned long long freq = ((double)frequency * (1.0 + _freq_corr * 0.000001)); + + // FIXME: gain_mode string can be manual / slow_attack / fast_attack / hybrid + _src->set_params( freq, samplerate, bandwidth, quadrature, rfdc, bbdc, + gain_auto ? "fast_attack" : "manual", gain_value, + filter.c_str(), filter_auto ); +} --- /dev/null +++ lib/plutosdr/plutosdr_source_c.h @@ -0,0 +1,105 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Dimitri Stolnikov + * + * 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 PLUTOSDR_SOURCE_C_H +#define PLUTOSDR_SOURCE_C_H + +#include +#include +#include +#include + +#include "source_iface.h" + +class plutosdr_source_c; + +typedef boost::shared_ptr< plutosdr_source_c > plutosdr_source_c_sptr; + +plutosdr_source_c_sptr make_plutosdr_source_c(const std::string &args = ""); + +class plutosdr_source_c : + public gr::hier_block2, + public source_iface +{ +private: + friend plutosdr_source_c_sptr make_plutosdr_source_c(const std::string &args); + + plutosdr_source_c(const std::string &args); + +public: + ~plutosdr_source_c(); + + static std::vector< std::string > get_devices(); + + std::string name(); + + 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 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 bw, size_t chan = 0 ); + double get_bandwidth( size_t chan = 0 ); + +private: + + void set_params(void); + + gr::iio::pluto_source::sptr _src; + + std::string uri; + unsigned long long frequency; + unsigned long samplerate; + unsigned long decimation; + unsigned long bandwidth; + unsigned long buffer_size; + bool quadrature; + bool rfdc; + bool bbdc; + bool gain_auto; + double gain_value; + std::string filter; + bool filter_auto; + + double _freq_corr; +}; + +#endif // PLUTOSDR_SOURCE_C_H --- lib/source_impl.cc.orig +++ lib/source_impl.cc @@ -96,6 +96,10 @@ #include #endif +#ifdef ENABLE_IIO +#include +#endif + #include "arg_helpers.h" #include "source_impl.h" @@ -172,6 +176,9 @@ #endif #ifdef ENABLE_XTRX dev_types.push_back("xtrx"); +#endif +#ifdef ENABLE_IIO + dev_types.push_back("plutosdr"); #endif std::cerr << "gr-osmosdr " << GR_OSMOSDR_VERSION << " (" << GR_OSMOSDR_LIBVER << ") " @@ -256,6 +263,10 @@ for (std::string dev : xtrx_source_c::get_devices()) dev_list.push_back( dev ); #endif +#ifdef ENABLE_IIO + for (std::string dev : plutosdr_source_c::get_devices()) + dev_list.push_back( dev ); +#endif // std::cerr << std::endl; // for (std::string dev : dev_list) @@ -394,6 +405,13 @@ } #endif +#ifdef ENABLE_IIO + if ( dict.count("plutosdr") ) { + plutosdr_source_c_sptr src = make_plutosdr_source_c( arg ); + block = src; iface = src.get(); + } +#endif + if ( iface != NULL && long(block.get()) != 0 ) { _devs.push_back( iface );