From 3ce7c3398102e49f5fe7411a8e0fb5700236a3c7 Mon Sep 17 00:00:00 2001 From: Dimitri Stolnikov Date: Sat, 13 Jul 2013 14:13:41 +0200 Subject: fcd: add support for FUNcube Dongle Pro+ The gnuradio block https://github.com/dl1ksv/gr-fcdproplus must be installed before building gr-osmosdr. Available named gains: Dongle Classic: LNA: -5 to 30 dB, in 2.5 dB steps MIX: 4 or 12 dB Dongle Pro+: LNA: 0 or 1, meaning off/on only. no information about real values. MIX: 0 or 1, meaning off/on only. no information about real values. BB: 0 to 59 dB, in 1 dB steps This patch also introduces optional "device" and "type" arguments which allow to override the values automatically picked by gr-osmosdr: osmocom_fft -a "fcd,device=hw:2,type=2" The "device" argument overrides the audio device used by the underlying driver to access the dongle's IQ sample stream. The "type" argument selects the dongle type, 1 for Classic, 2 for Pro+. Thanks to Alexey Bazhin for the initial patch and Volker Schroer for testing. --- lib/fcd/CMakeLists.txt | 19 +++- lib/fcd/fcd_source_c.cc | 250 ++++++++++++++++++++++++++++++++++++++++++------ lib/fcd/fcd_source_c.h | 26 ++++- 3 files changed, 257 insertions(+), 38 deletions(-) (limited to 'lib/fcd') diff --git a/lib/fcd/CMakeLists.txt b/lib/fcd/CMakeLists.txt index 94581f4..e71b153 100644 --- a/lib/fcd/CMakeLists.txt +++ b/lib/fcd/CMakeLists.txt @@ -21,10 +21,15 @@ # This file included, use CMake directory variables ######################################################################## -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} - ${GNURADIO_FCD_INCLUDE_DIRS} -) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +if(ENABLE_FCD) +include_directories(${GNURADIO_FCD_INCLUDE_DIRS}) +endif(ENABLE_FCD) + +if(ENABLE_FCDPP) +include_directories(${GNURADIO_FCDPP_INCLUDE_DIRS}) +endif(ENABLE_FCDPP) set(fcd_srcs ${CMAKE_CURRENT_SOURCE_DIR}/fcd_source_c.cc @@ -34,5 +39,11 @@ set(fcd_srcs # 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 c5a89b6..885d514 100644 --- a/lib/fcd/fcd_source_c.cc +++ b/lib/fcd/fcd_source_c.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2012 Dimitri Stolnikov + * Copyright 2013 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 @@ -42,10 +42,17 @@ fcd_source_c_sptr make_fcd_source_c(const std::string &args) 2 [V10 ]: USB-Audio - FUNcube Dongle V1.0 Hanlincrest Ltd. FUNcube Dongle V1.0 at usb-0000:00:1d.0-2, full speed */ +/* + 2 [V20 ]: USB-Audio - FUNcube Dongle V2.0 + Hanlincrest Ltd. FUNcube Dongle V2.0 at usb-0000:00:1d.0-2, full speed + */ + +typedef std::pair< fcd_source_c::dongle_type, std::string > device_t; +typedef std::vector< device_t > devices_t; -static std::vector< std::string > _get_devices() +static devices_t _get_devices() /* FIXME: non-portable way to discover dongles */ { - std::vector< std::string > devices; + devices_t devices; std::string line; std::ifstream cards( "/proc/asound/cards" ); @@ -55,15 +62,23 @@ static std::vector< std::string > _get_devices() { getline (cards, line); - if ( line.find( "USB-Audio - FUNcube Dongle" ) != std::string::npos ) + fcd_source_c::dongle_type type = fcd_source_c::FUNCUBE_UNKNOWN; + + if ( line.find( "USB-Audio - FUNcube Dongle V1.0" ) != std::string::npos ) + type = fcd_source_c::FUNCUBE_V1; + + if ( line.find( "USB-Audio - FUNcube Dongle V2.0" ) != std::string::npos ) + type = fcd_source_c::FUNCUBE_V2; + + if ( type != fcd_source_c::FUNCUBE_UNKNOWN ) { int id; std::istringstream( line ) >> id; std::ostringstream hw_id; - hw_id << "hw:" << id; // build alsa identifier + hw_id << "hw:" << id; /* build alsa identifier */ - devices += hw_id.str(); + devices += device_t( type, hw_id.str() ); } } @@ -76,7 +91,8 @@ static std::vector< std::string > _get_devices() fcd_source_c::fcd_source_c(const std::string &args) : gr::hier_block2("fcd_source_c", gr::io_signature::make(0, 0, 0), - gr::io_signature::make(1, 1, sizeof (gr_complex))) + gr::io_signature::make(1, 1, sizeof (gr_complex))), + _type( FUNCUBE_UNKNOWN ) { std::string dev_name; unsigned int dev_index = 0; @@ -84,18 +100,70 @@ fcd_source_c::fcd_source_c(const std::string &args) : dict_t dict = params_to_dict(args); if (dict.count("fcd")) - dev_index = boost::lexical_cast< unsigned int >( dict["fcd"] ); + { + std::string value = dict["fcd"]; + if ( value.length() ) + { + try { + dev_index = boost::lexical_cast< unsigned int >( value ); + } catch ( std::exception &ex ) { + throw std::runtime_error( + "Failed to use '" + value + "' as index: " + ex.what()); + } + } + } + + if (dict.count("device")) + { + dev_name = dict["device"]; + _type = FUNCUBE_V1; + } + + if (dict.count("type")) + { + _type = (dongle_type) boost::lexical_cast< int >( dict["type"] ); - std::vector< std::string > devices = _get_devices(); + if ( FUNCUBE_V1 != _type && FUNCUBE_V2 != _type ) + throw std::runtime_error("FUNcube Dongle type must be 1 or 2."); + } + + devices_t devices = _get_devices(); if ( devices.size() ) - dev_name = devices[dev_index]; - else - throw std::runtime_error("No FunCube Dongle found."); + { + if ( FUNCUBE_UNKNOWN == _type ) + _type = devices[dev_index].first; + + if ( dev_name.length() == 0 ) + dev_name = devices[dev_index].second; + } + else if ( dev_name.length() == 0 ) + throw std::runtime_error("No FUNcube Dongle found."); - _src = gr::fcd::source_c::make( dev_name ); + std::cerr << "Using " << name() << " (" << dev_name << ")" << std::endl; + +#ifdef HAVE_FCD + if ( FUNCUBE_V1 == _type ) + { + _src_v1 = gr::fcd::source_c::make( dev_name ); + connect( _src_v1, 0, self(), 0 ); + + set_gain( 20, "LNA" ); + set_gain( 12, "MIX" ); + } +#endif - connect( _src, 0, self(), 0 ); +#ifdef HAVE_FCDPP + if ( FUNCUBE_V2 == _type ) + { + _src_v2 = gr::fcdproplus::fcdproplus::make( dev_name ); + connect( _src_v2, 0, self(), 0 ); + + set_gain( 1, "LNA" ); + set_gain( 1, "MIX" ); + set_gain( 15, "BB" ); + } +#endif } fcd_source_c::~fcd_source_c() @@ -107,9 +175,15 @@ std::vector< std::string > fcd_source_c::get_devices() int id = 0; std::vector< std::string > devices; - BOOST_FOREACH( std::string dev, _get_devices() ) { + BOOST_FOREACH( device_t dev, _get_devices() ) + { std::string args = "fcd=" + boost::lexical_cast< std::string >( id++ ); - args += ",label='FunCube Dongle'"; + + if ( dev.first == fcd_source_c::FUNCUBE_V1 ) + args += ",label='FUNcube Dongle V1.0'"; + else if ( dev.first == fcd_source_c::FUNCUBE_V2 ) + args += ",label='FUNcube Dongle V2.0'"; + devices.push_back( args ); } @@ -118,7 +192,12 @@ std::vector< std::string > fcd_source_c::get_devices() std::string fcd_source_c::name() { - return "FUNcube Dongle"; + if ( FUNCUBE_V1 == _type ) + return "FUNcube Dongle V1.0"; + else if ( FUNCUBE_V2 == _type ) + return "FUNcube Dongle V2.0"; + + return ""; } size_t fcd_source_c::get_num_channels( void ) @@ -142,19 +221,35 @@ double fcd_source_c::set_sample_rate( double rate ) double fcd_source_c::get_sample_rate( void ) { - return 96e3; + if ( FUNCUBE_V1 == _type ) + return 96e3; + else if ( FUNCUBE_V2 == _type ) + return 192e3; + + return 0; } osmosdr::freq_range_t fcd_source_c::get_freq_range( size_t chan ) { - osmosdr::freq_range_t range( 52e6, 2.2e9 ); + if ( FUNCUBE_V1 == _type ) + return osmosdr::freq_range_t( 52e6, 2.2e9 ); + else if ( FUNCUBE_V2 == _type ) + return osmosdr::freq_range_t( 150e3, 2.05e9 ); - return range; + return osmosdr::freq_range_t(); } double fcd_source_c::set_center_freq( double freq, size_t chan ) { - _src->set_freq(float(freq)); +#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; @@ -168,7 +263,15 @@ double fcd_source_c::get_center_freq( size_t chan ) double fcd_source_c::set_freq_corr( double ppm, size_t chan ) { - _src->set_freq_corr( ppm ); +#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; @@ -185,44 +288,131 @@ std::vector fcd_source_c::get_gain_names( size_t chan ) std::vector< std::string > names; names += "LNA"; + names += "MIX"; + + if ( FUNCUBE_V2 == _type ) + names += "BB"; return names; } osmosdr::gain_range_t fcd_source_c::get_gain_range( size_t chan ) { - osmosdr::gain_range_t range(-5, 30, 2.5); + std::string name = ""; - return range; + if ( FUNCUBE_V1 == _type ) + name = "LNA"; /* use LNA gain for V1 dongle */ + else if ( FUNCUBE_V2 == _type ) + name = "BB"; /* use BB gain for V2 dongle */ + + return get_gain_range( name, chan ); } osmosdr::gain_range_t fcd_source_c::get_gain_range( const std::string & name, size_t chan ) { - return get_gain_range( chan ); + if ( FUNCUBE_V1 == _type ) + { + if ( "LNA" == name ) + return osmosdr::gain_range_t(-5, 30, 2.5); + else if ( "MIX" == name ) + return osmosdr::gain_range_t(4, 12, 8); + } + else if ( FUNCUBE_V2 == _type ) + { + if ( "LNA" == name ) + return osmosdr::gain_range_t(0, 1, 1); + else if ( "MIX" == name ) + return osmosdr::gain_range_t(0, 1, 1); + else if ( "BB" == name ) + return osmosdr::gain_range_t(0, 59, 1); + } + + return osmosdr::gain_range_t(); } double fcd_source_c::set_gain( double gain, size_t chan ) { - _src->set_lna_gain(gain); + if ( FUNCUBE_V1 == _type ) + _lna_gain = set_gain( gain, "LNA" ); - _gain = gain; + if ( FUNCUBE_V2 == _type ) + _bb_gain = set_gain( gain, "BB" ); return get_gain(chan); } double fcd_source_c::set_gain( double gain, const std::string & name, size_t chan ) { - return set_gain(chan); +#ifdef HAVE_FCD + if ( FUNCUBE_V1 == _type ) + { + if ( "LNA" == name ) + { + _lna_gain = gain; + _src_v1->set_lna_gain(_lna_gain); + } + else if ( "MIX" == name ) + { + _mix_gain = gain > 4 ? 12 : 4; + _src_v1->set_mixer_gain(_mix_gain); + } + } +#endif + +#ifdef HAVE_FCDPP + if ( FUNCUBE_V2 == _type ) + { + if ( "LNA" == name ) + { + _lna_gain = gain > 0 ? 1 : 0; + _src_v2->set_lna(_lna_gain); + } + else if ( "MIX" == name ) + { + _mix_gain = gain > 0 ? 1 : 0; + _src_v2->set_mixer_gain(_mix_gain); + } + else if ( "BB" == name ) + { + _bb_gain = gain; + _src_v2->set_if_gain(_bb_gain); + } + } +#endif + + return get_gain( name, chan ); } double fcd_source_c::get_gain( size_t chan ) { - return _gain; + if ( FUNCUBE_V1 == _type ) + return get_gain( "LNA", chan ); + else if ( FUNCUBE_V2 == _type ) + return get_gain( "BB", chan ); + + return 0; } double fcd_source_c::get_gain( const std::string & name, size_t chan ) { - return get_gain(chan); + if ( FUNCUBE_V1 == _type ) + { + if ( "LNA" == name ) + return _lna_gain; + else if ( "MIX" == name ) + return _mix_gain; + } + else if ( FUNCUBE_V2 == _type ) + { + if ( "LNA" == name ) + return _lna_gain; + else if ( "MIX" == name ) + return _mix_gain; + else if ( "BB" == name ) + return _bb_gain; + } + + return 0; } std::vector< std::string > fcd_source_c::get_antennas( size_t chan ) diff --git a/lib/fcd/fcd_source_c.h b/lib/fcd/fcd_source_c.h index c134a4c..70239f8 100644 --- a/lib/fcd/fcd_source_c.h +++ b/lib/fcd/fcd_source_c.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2012 Dimitri Stolnikov + * Copyright 2013 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 @@ -22,7 +22,13 @@ #include +#ifdef HAVE_FCD #include +#endif + +#ifdef HAVE_FCDPP +#include +#endif #include "source_iface.h" @@ -44,6 +50,12 @@ private: public: ~fcd_source_c(); + enum dongle_type { + FUNCUBE_UNKNOWN, + FUNCUBE_V1, + FUNCUBE_V2 + }; + static std::vector< std::string > get_devices(); std::string name(); @@ -73,9 +85,15 @@ public: std::string get_antenna( size_t chan = 0 ); private: - gr::fcd::source_c::sptr _src; - double _gain, _freq; - int32_t _correct; + dongle_type _type; +#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; }; #endif // FCD_SOURCE_C_H -- cgit v1.2.3