first working multichannel source

This commit is contained in:
Dimitri Stolnikov 2012-04-28 20:18:14 +02:00
parent 31a4356ba5
commit c1c0c2f212
15 changed files with 394 additions and 168 deletions

View File

@ -28,6 +28,8 @@
#include <fcd_source.h>
#include <osmosdr_arg_helpers.h>
using namespace boost::assign;
fcd_source_sptr make_fcd_source(const std::string &args)
@ -40,19 +42,22 @@ fcd_source::fcd_source(const std::string &args) :
gr_make_io_signature (0, 0, 0),
gr_make_io_signature (1, 1, sizeof (gr_complex)))
{
std::string device_name = args;
std::string dev_name;
unsigned int dev_index = 0;
dict_t dict = params_to_dict(args);
if (dict.count("fcd"))
dev_index = boost::lexical_cast< unsigned int >( dict["fcd"] );
if ( device_name.empty() )
{
std::vector< std::string > devices = fcd_source::get_devices();
if ( devices.size() )
device_name = devices.front(); // pick first available device
dev_name = devices[dev_index];
else
throw std::runtime_error("no FUNcube Dongle device found");
}
throw std::runtime_error("No FunCube Dongle found.");
_src = fcd_make_source_c( device_name );
_src = fcd_make_source_c( dev_name );
connect( _src, 0, self(), 0 );
}
@ -223,4 +228,3 @@ std::string fcd_source::get_antenna( size_t chan )
{
return "ANT";
}

View File

@ -32,7 +32,8 @@ typedef boost::shared_ptr< fcd_source > fcd_source_sptr;
fcd_source_sptr make_fcd_source( const std::string & args = "" );
class fcd_source : public gr_hier_block2,
class fcd_source :
public gr_hier_block2,
public osmosdr_src_iface
{
private:

View File

@ -27,7 +27,7 @@
#include "config.h"
#endif
#include <osmosdr_snk_c.h>
#include "osmosdr_snk_c.h"
#include <gr_io_signature.h>
#include <gr_audio_sink.h>
#include <gr_complex_to_xxx.h>
@ -49,7 +49,7 @@ osmosdr_make_snk_c (const std::string &args)
* 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 1 input and 1 output.
* only 1 input and 0 output.
*/
static const int MIN_IN = 1; // mininum number of input streams
static const int MAX_IN = 1; // maximum number of input streams

View File

@ -54,7 +54,8 @@ OSMOSDR_API osmosdr_snk_c_sptr osmosdr_make_snk_c (const std::string & args = ""
*
* This uses the preferred technique: subclassing gr_hier_block2.
*/
class OSMOSDR_API osmosdr_snk_c : public gr_hier_block2,
class OSMOSDR_API osmosdr_snk_c :
public gr_hier_block2,
public osmosdr_tx_control
{
private:

View File

@ -31,6 +31,8 @@
#include <gr_audio_source.h>
#include <gr_float_to_complex.h>
#include <osmosdr_arg_helpers.h>
/*
* Create a new instance of osmosdr_src_c and return
* a boost shared_ptr. This is effectively the public constructor.
@ -41,27 +43,13 @@ osmosdr_make_src_c (const std::string &args)
return gnuradio::get_initial_sptr(new osmosdr_src_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 1 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
*/
osmosdr_src_c::osmosdr_src_c (const std::string &args)
: gr_hier_block2 ("osmosdr_src_c",
gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex)),
gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex))),
gr_make_io_signature (0, 0, sizeof (gr_complex)),
args_to_io_signature(args)),
osmosdr_rx_control(args)
{
/* Audio source; sample rate is 500kHz by default */

View File

@ -54,7 +54,8 @@ OSMOSDR_API osmosdr_src_c_sptr osmosdr_make_src_c (const std::string & args = ""
*
* \sa osmosdr_sink_c for a version that subclasses gr_hier_block2.
*/
class OSMOSDR_API osmosdr_src_c : public gr_hier_block2,
class OSMOSDR_API osmosdr_src_c :
public gr_hier_block2,
public osmosdr_rx_control
{
private:

View File

@ -31,6 +31,9 @@
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
typedef std::map< std::string, std::string > dict_t;
typedef std::pair<std::string, std::string> pair_t;
inline std::vector< std::string > args_to_vector( const std::string &args )
{
std::vector< std::string > result;
@ -59,25 +62,91 @@ inline std::vector< std::string > params_to_vector( const std::string &params )
return result;
}
typedef std::map< std::string, std::string > dict_t;
inline pair_t param_to_pair( const std::string &param )
{
pair_t result;
std::size_t pos = param.find('=');
if(pos != std::string::npos)
{
result.first = param.substr(0, pos);
result.second = param.substr(pos + 1);
}
else
{
result.first = param;
result.second = "";
}
return result;
}
inline dict_t params_to_dict( const std::string &params )
{
dict_t result;
std::vector< std::string > param_list = params_to_vector( params );
BOOST_FOREACH(std::string param, param_list) {
std::cout << "D'" << param << "'" << std::endl;
BOOST_FOREACH(std::string param, param_list)
{
pair_t nchan = param_to_pair( param );
std::string value = nchan.second;
if (value.length() && value[0] == '\'' && value[ value.length() - 1 ] == '\'')
value = value.substr(1, value.length() - 1);
result[ nchan.first ] = nchan.second;
}
return result;
}
struct is_nchan_argument
{
bool operator ()(const std::string &str)
{
return str.find("nchan=") == 0;
}
};
inline gr_io_signature_sptr args_to_io_signature( const std::string &args )
{
size_t max_nchan = 0;
size_t dev_nchan = 0;
std::vector< std::string > arg_list = args_to_vector( args );
const size_t nchan = std::max<size_t>(arg_list.size(), 1);
BOOST_FOREACH( std::string arg, arg_list )
{
if ( arg.find( "nchan=" ) == 0 ) // try to parse global nchan value
{
pair_t pair = param_to_pair( arg );
max_nchan = boost::lexical_cast<size_t>( pair.second );
}
}
arg_list.erase( std::remove_if( // remove any global nchan tokens
arg_list.begin(),
arg_list.end(),
is_nchan_argument() ),
arg_list.end() );
// try to parse device specific nchan values, assume 1 channel if none given
BOOST_FOREACH( std::string arg, arg_list )
{
dict_t dict = params_to_dict(arg);
if (dict.count("nchan"))
{
dev_nchan += boost::lexical_cast<size_t>( dict["nchan"] );
}
else // no channels given via args
{
dev_nchan++; // assume one channel
}
}
// 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?");
const size_t nchan = std::max<size_t>(dev_nchan, 1); // assume at least one
return gr_make_io_signature(nchan, nchan, sizeof(gr_complex));
}

View File

@ -47,12 +47,12 @@ osmosdr_make_sink_c (const std::string &args)
* 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 1 input and 1 output.
* only 1 input and 0 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
static const int MIN_IN = 1; // mininum number of input streams
static const int MAX_IN = 1; // maximum number of input streams
static const int MIN_OUT = 0; // minimum number of output streams
static const int MAX_OUT = 0; // maximum number of output streams
/*
* The private constructor

View File

@ -30,6 +30,22 @@
#include <osmosdr_source_c_impl.h>
#include <gr_io_signature.h>
#ifdef ENABLE_OSMOSDR
#include <osmosdr_src_c.h>
#endif
#ifdef ENABLE_FCD
#include <fcd_source.h>
#endif
#ifdef ENABLE_RTL
#include <rtl_source_c.h>
#endif
#ifdef ENABLE_UHD
#include <uhd_source_c.h>
#endif
#include <osmosdr_arg_helpers.h>
/*
@ -50,34 +66,65 @@ osmosdr_source_c_impl::osmosdr_source_c_impl (const std::string &args)
gr_make_io_signature (0, 0, 0),
args_to_io_signature(args))
{
std::vector< std::string > arg_list = args_to_vector(args);
size_t channel = 0;
std::cout << "arg_list.size: " << arg_list.size() << std::endl;
BOOST_FOREACH(std::string arg, args_to_vector(args)) {
BOOST_FOREACH(std::string arg, arg_list) {
dict_t dict = params_to_dict(arg);
std::cout << "" << std::endl;
BOOST_FOREACH( dict_t::value_type &entry, dict )
std::cout << "'" << entry.first << "' '" << entry.second << "'" << std::endl;
// std::cout << std::endl;
// BOOST_FOREACH( dict_t::value_type &entry, dict )
// std::cout << "'" << entry.first << "' = '" << entry.second << "'" << std::endl;
#ifdef ENABLE_OSMOSDR
if ( dict.count("osmosdr") ) {
osmosdr_src_c_sptr src = osmosdr_make_src_c( arg );
// for (size_t i = 0; i < src->get_num_channels(); i++)
// connect(src, i, self(), channel++);
// _srcs.push_back( (osmosdr_src_iface *)src.get() ); // FIXME: implement
}
#endif
for ( int i = 0; i < 1; i++ ) {
std::string arg = boost::lexical_cast<std::string>(i);
#ifdef ENABLE_FCD
if ( dict.count("fcd") ) {
fcd_source_sptr src = make_fcd_source( arg );
connect(src, 0, self(), channel++);
_srcs.push_back( (osmosdr_src_iface *)src.get() );
}
#endif
#ifdef ENABLE_RTL
if ( dict.count("rtl") ) {
rtl_source_c_sptr src = make_rtl_source_c( arg );
connect(src, 0, self(), i);
_srcs.push_back( src );
connect(src, 0, self(), channel++);
_srcs.push_back( (osmosdr_src_iface *)src.get() );
}
#endif
#ifdef ENABLE_UHD
if ( dict.count("uhd") ) {
uhd_source_c_sptr src = make_uhd_source_c( arg );
for (size_t i = 0; i < src->get_num_channels(); i++)
connect(src, i, self(), channel++);
_srcs.push_back( (osmosdr_src_iface *)src.get() );
}
#endif
}
if (!_srcs.size())
throw std::runtime_error("No devices specified via device arguments.");
}
size_t osmosdr_source_c_impl::get_num_channels()
{
size_t channels = 0;
channels = _srcs[0]->get_num_channels();
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
channels += dev->get_num_channels();
return channels;
}
@ -89,8 +136,12 @@ osmosdr::meta_range_t osmosdr_source_c_impl::get_sample_rates()
double osmosdr_source_c_impl::set_sample_rate(double rate)
{
return _srcs[0]->set_sample_rate(rate);
// return rate;
double sample_rate = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
sample_rate = dev->set_sample_rate(rate);
return sample_rate;
}
double osmosdr_source_c_impl::get_sample_rate()
@ -100,76 +151,165 @@ double osmosdr_source_c_impl::get_sample_rate()
osmosdr::freq_range_t osmosdr_source_c_impl::get_freq_range( size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_freq_range( chan );
return osmosdr::freq_range_t();
}
double osmosdr_source_c_impl::set_center_freq( double freq, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->set_center_freq( freq, chan );
// return freq;
return 0;
}
double osmosdr_source_c_impl::get_center_freq( size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_center_freq( chan );
return 0;
}
double osmosdr_source_c_impl::set_freq_corr( double ppm, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->set_freq_corr( ppm, chan );
return 0;
}
double osmosdr_source_c_impl::get_freq_corr( size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_freq_corr( chan );
return 0;
}
std::vector<std::string> osmosdr_source_c_impl::get_gain_names( size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_gain_names( chan );
return std::vector< std::string >();
}
osmosdr::gain_range_t osmosdr_source_c_impl::get_gain_range( size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_gain_range( chan );
return osmosdr::gain_range_t();
}
osmosdr::gain_range_t osmosdr_source_c_impl::get_gain_range( const std::string & name, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_gain_range( name, chan );
return osmosdr::gain_range_t();
}
double osmosdr_source_c_impl::set_gain( double gain, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->set_gain( gain, chan );
return 0;
}
double osmosdr_source_c_impl::set_gain( double gain, const std::string & name, size_t chan)
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->set_gain( gain, name, chan );
return 0;
}
double osmosdr_source_c_impl::get_gain( size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_gain( chan );
return 0;
}
double osmosdr_source_c_impl::get_gain( const std::string & name, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_gain( name, chan );
return 0;
}
std::vector< std::string > osmosdr_source_c_impl::get_antennas( size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_antennas( chan );
return std::vector< std::string >();
}
std::string osmosdr_source_c_impl::set_antenna( const std::string & antenna, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->set_antenna( antenna, chan );
return "";
}
std::string osmosdr_source_c_impl::get_antenna( size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( osmosdr_src_iface *dev, _srcs )
for (size_t i = 0; i < dev->get_num_channels(); i++)
if ( chan == channel++ )
return _srcs[chan]->get_antenna( chan );
return "";
}

View File

@ -23,7 +23,7 @@
#include <osmosdr_api.h>
#include <osmosdr_source_c.h>
#include <rtl_source_c.h>
#include <osmosdr_src_iface.h>
class OSMOSDR_API osmosdr_source_c_impl : public osmosdr_source_c
{
@ -60,7 +60,7 @@ private:
friend OSMOSDR_API osmosdr_source_c_sptr osmosdr_make_source_c (const std::string & args);
size_t _nchan;
std::vector< rtl_source_c_sptr > _srcs;
std::vector< osmosdr_src_iface * > _srcs;
};
#endif /* INCLUDED_OSMOSDR_SOURCE_C_IMPL_H */

View File

@ -38,6 +38,8 @@
#include <rtl-sdr.h>
#include <osmosdr_arg_helpers.h>
using namespace boost::assign;
#define BUF_SIZE (16 * 32 * 512)
@ -59,7 +61,7 @@ make_rtl_source_c (const std::string &args)
* 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 1 input and 1 output.
* 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
@ -75,9 +77,12 @@ rtl_source_c::rtl_source_c (const std::string &args)
gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
{
int ret;
unsigned int dev_index = atoi( args.c_str() );
unsigned int dev_index = 0;
std::cout << "'" << args << "'" << std::endl;
dict_t dict = params_to_dict(args);
if (dict.count("rtl"))
dev_index = boost::lexical_cast< unsigned int >( dict["rtl"] );
_buf_num = 32;
_buf = (unsigned short **) malloc(_buf_num * sizeof(unsigned short *));

View File

@ -61,7 +61,8 @@ OSMOSDR_API rtl_source_c_sptr make_rtl_source_c (const std::string & args = "");
* \ingroup block
*
*/
class OSMOSDR_API rtl_source_c : public gr_sync_block,
class OSMOSDR_API rtl_source_c :
public gr_sync_block,
public osmosdr_src_iface
{
private:

View File

@ -25,6 +25,8 @@
#include <gr_io_signature.h>
#include <osmosdr_arg_helpers.h>
#include "uhd_source_c.h"
using namespace boost::assign;
@ -37,11 +39,24 @@ uhd_source_c_sptr make_uhd_source_c(const std::string &args)
uhd_source_c::uhd_source_c(const std::string &args) :
gr_hier_block2("uhd_source_c",
gr_make_io_signature (0, 0, 0),
gr_make_io_signature (1, 1, sizeof (gr_complex)))
args_to_io_signature(args))
{
_src = uhd_make_usrp_source( args, uhd::io_type_t::COMPLEX_FLOAT32, 1 );
size_t num_channels = 1;
connect( _src, 0, self(), 0 );
dict_t dict = params_to_dict(args);
if (dict.count("nchan"))
num_channels = boost::lexical_cast< unsigned int >( dict["nchan"] );
_src = uhd_make_usrp_source( args,
uhd::io_type_t::COMPLEX_FLOAT32,
num_channels );
if (dict.count("subdev"))
_src->set_subdev_spec( dict["subdev"] );
for ( size_t i = 0; i < num_channels; i++ )
connect( _src, i, self(), i );
}
uhd_source_c::~uhd_source_c()
@ -132,7 +147,7 @@ double uhd_source_c::set_freq_corr( double ppm, size_t chan )
double uhd_source_c::get_freq_corr( size_t chan )
{
throw std::runtime_error( "frequency correction is not supported with UHD" );
return 0; // frequency correction is not supported with UHD
}
std::vector<std::string> uhd_source_c::get_gain_names( size_t chan )

View File

@ -32,7 +32,8 @@ typedef boost::shared_ptr< uhd_source_c > uhd_source_c_sptr;
uhd_source_c_sptr make_uhd_source_c(const std::string &args = "");
class uhd_source_c : public gr_hier_block2,
class uhd_source_c :
public gr_hier_block2,
public osmosdr_src_iface
{
private: