aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDimitri Stolnikov <horiz0n@gmx.net>2012-04-06 15:29:14 +0200
committerDimitri Stolnikov <horiz0n@gmx.net>2012-04-06 15:29:14 +0200
commit0efd28de6bc86c3e474cfad70d1e5889575224a7 (patch)
treed3d12127a6315f026505629bec961d32696271e6 /lib
initial commit
Diffstat (limited to 'lib')
-rw-r--r--lib/CMakeLists.txt57
-rw-r--r--lib/osmosdr_ranges.cc163
-rw-r--r--lib/osmosdr_sink_c_impl.cc69
-rw-r--r--lib/osmosdr_sink_c_impl.h41
-rw-r--r--lib/osmosdr_source_c_impl.cc136
-rw-r--r--lib/osmosdr_source_c_impl.h60
-rw-r--r--lib/rtl_source_c.cc229
-rw-r--r--lib/rtl_source_c.h104
8 files changed, 859 insertions, 0 deletions
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644
index 0000000..40c0a58
--- /dev/null
+++ b/lib/CMakeLists.txt
@@ -0,0 +1,57 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Setup library
+########################################################################
+include(GrPlatform) #define LIB_SUFFIX
+
+add_library(gnuradio-osmosdr SHARED
+ osmosdr_ranges.cc
+ osmosdr_sink_c_impl.cc
+ osmosdr_source_c_impl.cc
+ rtl_source_c.cc
+)
+
+target_link_libraries(gnuradio-osmosdr
+ ${Boost_LIBRARIES}
+ ${GRUEL_LIBRARIES}
+ ${GNURADIO_CORE_LIBRARIES}
+# ${GNURADIO_AUDIO_LIBRARIES}
+ ${LIBRTLSDR_LIBRARIES}
+)
+
+set_target_properties(gnuradio-osmosdr PROPERTIES DEFINE_SYMBOL "gnuradio_osmosdr_EXPORTS")
+
+########################################################################
+# Install built library files
+########################################################################
+install(TARGETS gnuradio-osmosdr
+ LIBRARY DESTINATION lib${LIB_SUFFIX} # .so/.dylib file
+ ARCHIVE DESTINATION lib${LIB_SUFFIX} # .lib file
+ RUNTIME DESTINATION bin # .dll file
+)
+
+########################################################################
+# Add subdirectories
+########################################################################
+#add_subdirectory(fcd)
+#add_subdirectory(osmosdr)
+#add_subdirectory(rtl)
+#add_subdirectory(uhd)
diff --git a/lib/osmosdr_ranges.cc b/lib/osmosdr_ranges.cc
new file mode 100644
index 0000000..86a8d16
--- /dev/null
+++ b/lib/osmosdr_ranges.cc
@@ -0,0 +1,163 @@
+//
+// Copyright 2011-2011 Ettus Research LLC
+//
+// This program 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 of the License, or
+// (at your option) any later version.
+//
+// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <osmosdr_ranges.h>
+#include <stdexcept>
+#include <boost/math/special_functions/round.hpp>
+#include <boost/foreach.hpp>
+#include <algorithm>
+#include <sstream>
+
+using namespace osmosdr;
+
+/***********************************************************************
+ * range_t implementation code
+ **********************************************************************/
+struct range_t::impl{
+ impl(double start, double stop, double step):
+ start(start), stop(stop), step(step)
+ {
+ /* NOP */
+ }
+ double start, stop, step;
+};
+
+range_t::range_t(double value):
+ _impl(OSMOSDR_PIMPL_MAKE(impl, (value, value, 0)))
+{
+ /* NOP */
+}
+
+range_t::range_t(
+ double start, double stop, double step
+):
+ _impl(OSMOSDR_PIMPL_MAKE(impl, (start, stop, step)))
+{
+ if (stop < start){
+ throw std::runtime_error("cannot make range where stop < start");
+ }
+}
+
+double range_t::start(void) const{
+ return _impl->start;
+}
+
+double range_t::stop(void) const{
+ return _impl->stop;
+}
+
+double range_t::step(void) const{
+ return _impl->step;
+}
+
+const std::string range_t::to_pp_string(void) const{
+ std::stringstream ss;
+ ss << "(" << this->start();
+ if (this->start() != this->stop()) ss << ", " << this->stop();
+ if (this->step() != 0) ss << ", " << this->step();
+ ss << ")";
+ return ss.str();
+}
+
+/***********************************************************************
+ * meta_range_t implementation code
+ **********************************************************************/
+void check_meta_range_monotonic(const meta_range_t &mr){
+ if (mr.empty()){
+ throw std::runtime_error("meta-range cannot be empty");
+ }
+ for (size_t i = 1; i < mr.size(); i++){
+ if (mr.at(i).start() < mr.at(i-1).stop()){
+ throw std::runtime_error("meta-range is not monotonic");
+ }
+ }
+}
+
+meta_range_t::meta_range_t(void){
+ /* NOP */
+}
+
+meta_range_t::meta_range_t(
+ double start, double stop, double step
+):
+ std::vector<range_t > (1, range_t(start, stop, step))
+{
+ /* NOP */
+}
+
+double meta_range_t::start(void) const{
+ check_meta_range_monotonic(*this);
+ double min_start = this->front().start();
+ BOOST_FOREACH(const range_t &r, (*this)){
+ min_start = std::min(min_start, r.start());
+ }
+ return min_start;
+}
+
+double meta_range_t::stop(void) const{
+ check_meta_range_monotonic(*this);
+ double max_stop = this->front().stop();
+ BOOST_FOREACH(const range_t &r, (*this)){
+ max_stop = std::max(max_stop, r.stop());
+ }
+ return max_stop;
+}
+
+double meta_range_t::step(void) const{
+ check_meta_range_monotonic(*this);
+ std::vector<double> non_zero_steps;
+ range_t last = this->front();
+ 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
+ double ibtw_step = r.start() - last.stop();
+ if (ibtw_step > 0) non_zero_steps.push_back(ibtw_step);
+ //store ref to last
+ last = r;
+ }
+ if (non_zero_steps.empty()) return 0; //all zero steps, its zero...
+ return *std::min_element(non_zero_steps.begin(), non_zero_steps.end());
+}
+
+double meta_range_t::clip(double value, bool clip_step) const{
+ check_meta_range_monotonic(*this);
+ double last_stop = this->front().stop();
+ 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))?
+ r.start() : last_stop;
+ }
+ //in this range, clip here
+ if (value <= r.stop()){
+ if (not clip_step or r.step() == 0) return value;
+ return boost::math::round((value - r.start())/r.step())*r.step() + r.start();
+ }
+ //continue on to the next range
+ last_stop = r.stop();
+ }
+ return last_stop;
+}
+
+const std::string meta_range_t::to_pp_string(void) const{
+ std::stringstream ss;
+ BOOST_FOREACH(const range_t &r, (*this)){
+ ss << r.to_pp_string() << std::endl;
+ }
+ return ss.str();
+}
diff --git a/lib/osmosdr_sink_c_impl.cc b/lib/osmosdr_sink_c_impl.cc
new file mode 100644
index 0000000..f5b2ec6
--- /dev/null
+++ b/lib/osmosdr_sink_c_impl.cc
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ *
+ * 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.
+ */
+
+/*
+ * 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_sink_c_impl.h>
+#include <gr_io_signature.h>
+
+/*
+ * Create a new instance of osmosdr_sink_c_impl and return
+ * a boost shared_ptr. This is effectively the public constructor.
+ */
+osmosdr_sink_c_sptr
+osmosdr_make_sink_c (const std::string &args)
+{
+ return gnuradio::get_initial_sptr(new osmosdr_sink_c_impl (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_sink_c_impl::osmosdr_sink_c_impl (const std::string &args)
+ : gr_hier_block2 ("osmosdr_sink_c_impl",
+ gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex)),
+ gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
+{
+ //connect(_src, 0, self(), 0);
+}
diff --git a/lib/osmosdr_sink_c_impl.h b/lib/osmosdr_sink_c_impl.h
new file mode 100644
index 0000000..44d66c9
--- /dev/null
+++ b/lib/osmosdr_sink_c_impl.h
@@ -0,0 +1,41 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ *
+ * 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.
+ */
+#ifndef INCLUDED_OSMOSDR_SINK_C_IMPL_H
+#define INCLUDED_OSMOSDR_SINK_C_IMPL_H
+
+#include <osmosdr_api.h>
+#include <osmosdr_sink_c.h>
+
+class OSMOSDR_API osmosdr_sink_c_impl : public osmosdr_sink_c
+{
+public:
+
+private:
+ osmosdr_sink_c_impl (const std::string & args); // private constructor
+
+ // The friend declaration allows osmosdr_make_sink_c to
+ // access the private constructor.
+ friend OSMOSDR_API osmosdr_sink_c_sptr osmosdr_make_sink_c (const std::string & args);
+};
+
+#endif /* INCLUDED_OSMOSDR_SINK_C_IMPL_H */
diff --git a/lib/osmosdr_source_c_impl.cc b/lib/osmosdr_source_c_impl.cc
new file mode 100644
index 0000000..46734a8
--- /dev/null
+++ b/lib/osmosdr_source_c_impl.cc
@@ -0,0 +1,136 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ *
+ * 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.
+ */
+
+/*
+ * 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_source_c_impl.h>
+#include <gr_io_signature.h>
+
+/*
+ * Create a new instance of osmosdr_source_c_impl and return
+ * a boost shared_ptr. This is effectively the public constructor.
+ */
+osmosdr_source_c_sptr
+osmosdr_make_source_c (const std::string &args)
+{
+ return gnuradio::get_initial_sptr(new osmosdr_source_c_impl (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_source_c_impl::osmosdr_source_c_impl (const std::string &args)
+ : gr_hier_block2 ("osmosdr_source_c_impl",
+ gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex)),
+ gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
+{
+ _src = make_rtl_source_c( args );
+
+ connect(_src, 0, self(), 0);
+}
+
+osmosdr::meta_range_t osmosdr_source_c_impl::get_samp_rates( void )
+{
+
+}
+
+double osmosdr_source_c_impl::set_samp_rate( double rate )
+{
+ return _src->set_sample_rate( rate );
+}
+
+double osmosdr_source_c_impl::get_samp_rate( void )
+{
+ return _src->get_sample_rate();
+}
+
+osmosdr::freq_range_t osmosdr_source_c_impl::get_freq_range( size_t chan )
+{
+
+}
+
+double osmosdr_source_c_impl::set_center_freq( double freq, size_t chan )
+{
+ return _src->set_center_freq( freq );
+}
+
+double osmosdr_source_c_impl::get_center_freq( size_t chan )
+{
+
+}
+
+double osmosdr_source_c_impl::set_freq_correction( double ppm, size_t chan )
+{
+
+}
+
+double osmosdr_source_c_impl::get_freq_correction( size_t chan )
+{
+
+}
+
+std::vector<std::string> osmosdr_source_c_impl::get_gain_names( size_t chan )
+{
+
+}
+
+osmosdr::gain_range_t osmosdr_source_c_impl::get_gain_range( const std::string & name, size_t chan )
+{
+
+}
+
+void osmosdr_source_c_impl::set_gain( double gain, size_t chan )
+{
+ _src->set_gain( gain );
+}
+
+void osmosdr_source_c_impl::set_gain( double gain, const std::string & name, size_t chan )
+{
+
+}
+
+double osmosdr_source_c_impl::get_gain( const std::string & name, size_t chan )
+{
+
+}
diff --git a/lib/osmosdr_source_c_impl.h b/lib/osmosdr_source_c_impl.h
new file mode 100644
index 0000000..91bf953
--- /dev/null
+++ b/lib/osmosdr_source_c_impl.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ *
+ * 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.
+ */
+#ifndef INCLUDED_OSMOSDR_SOURCE_C_IMPL_H
+#define INCLUDED_OSMOSDR_SOURCE_C_IMPL_H
+
+#include <osmosdr_api.h>
+#include <osmosdr_source_c.h>
+
+#include <rtl_source_c.h>
+
+class OSMOSDR_API osmosdr_source_c_impl : public osmosdr_source_c
+{
+public:
+ osmosdr::meta_range_t get_samp_rates( void );
+ double set_samp_rate( double rate );
+ double get_samp_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_correction( double ppm, size_t chan = 0 );
+ double get_freq_correction( size_t chan = 0 );
+
+ std::vector<std::string> get_gain_names( size_t chan = 0 );
+ osmosdr::gain_range_t get_gain_range( const std::string & name = "", size_t chan = 0 );
+ void set_gain( double gain, size_t chan = 0 );
+ void set_gain( double gain, const std::string & name = "", size_t chan = 0 );
+ double get_gain( const std::string & name = "", size_t chan = 0 );
+
+private:
+ osmosdr_source_c_impl (const std::string & args); // private constructor
+
+ // The friend declaration allows osmosdr_make_source_c to
+ // access the private constructor.
+ friend OSMOSDR_API osmosdr_source_c_sptr osmosdr_make_source_c (const std::string & args);
+
+ rtl_source_c_sptr _src;
+};
+
+#endif /* INCLUDED_OSMOSDR_SOURCE_C_IMPL_H */
diff --git a/lib/rtl_source_c.cc b/lib/rtl_source_c.cc
new file mode 100644
index 0000000..82001f9
--- /dev/null
+++ b/lib/rtl_source_c.cc
@@ -0,0 +1,229 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ *
+ * 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.
+ */
+
+/*
+ * 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 <rtl_source_c.h>
+#include <gr_io_signature.h>
+
+#include <stdexcept>
+#include <iostream>
+#include <stdio.h>
+
+#include <rtl-sdr.h>
+
+/*
+ * Create a new instance of rtl_source_c and return
+ * a boost shared_ptr. This is effectively the public constructor.
+ */
+rtl_source_c_sptr
+make_rtl_source_c (const std::string &args)
+{
+ return gnuradio::get_initial_sptr(new rtl_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 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
+ */
+rtl_source_c::rtl_source_c (const std::string &args)
+ : gr_sync_block ("rtl_source_c",
+ gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex)),
+ gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
+{
+ int ret;
+ int dev_index = 0;
+
+ _buf = boost::circular_buffer<unsigned char>(1024*1024);
+
+ // create a lookup table for gr_complex values
+ for (unsigned int i = 0; i <= 0xffff; i++)
+ {
+ _lut.push_back( gr_complex( ((i >> 8) - 127) * 0.00787,
+ ((i & 0xff) - 127) * 0.00787 ) );
+ }
+
+ std::cout << "Opening " << rtlsdr_get_device_name(dev_index) << std::endl;
+
+ _dev = NULL;
+ ret = rtlsdr_open(&_dev, dev_index);
+ if (ret < 0)
+ throw std::runtime_error("failed to open rtlsdr device.");
+
+ ret = rtlsdr_reset_buffer(_dev);
+ if (ret < 0)
+ throw std::runtime_error("failed to reset usb buffers.");
+
+ rtlsdr_set_sample_rate( _dev, 2048000 );
+
+ _has_i_sample = false;
+
+ _thread = gruel::thread(_rtlsdr_wait, this);
+}
+
+/*
+ * Our virtual destructor.
+ */
+rtl_source_c::~rtl_source_c ()
+{
+ if (_dev) {
+ rtlsdr_cancel_async( _dev );
+ _thread.join();
+ rtlsdr_close( _dev );
+ _dev = NULL;
+ }
+}
+
+void rtl_source_c::_rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
+{
+ rtl_source_c *obj = (rtl_source_c *)ctx;
+ obj->rtlsdr_callback(buf, len);
+}
+
+void rtl_source_c::rtlsdr_callback(unsigned char *buf, uint32_t len)
+{
+ boost::mutex::scoped_lock lock( _buf_mutex );
+
+ for (int i = 0; i < len; i++) {
+ if (!_buf.full()) {
+ _buf.push_back(buf[i]);
+ _buf_cond.notify_one();
+ } else {
+ printf("O"); fflush(stdout);
+ break;
+ }
+ }
+}
+
+void rtl_source_c::_rtlsdr_wait(rtl_source_c *obj)
+{
+ obj->rtlsdr_wait();
+}
+
+void rtl_source_c::rtlsdr_wait()
+{
+ int ret = rtlsdr_wait_async(_dev, _rtlsdr_callback, (void *)this);
+ if (-10 == ret)
+ ret = rtlsdr_wait_async(_dev, _rtlsdr_callback, (void *)this);
+
+ std::cout << "rtlsdr_wait() finished due to " << ret << std::endl;
+}
+
+int rtl_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];
+
+ unsigned short index = 0;
+
+ int items_left = noutput_items;
+ while ( items_left )
+ {
+ {
+ boost::mutex::scoped_lock lock( _buf_mutex );
+
+ while( _buf.empty() ) {
+ _buf_cond.wait( lock );
+ }
+ }
+
+ if (!_has_i_sample) {
+ index = _buf.front() << 8;
+ _buf.pop_front();
+ _has_i_sample = true;
+ } else {
+ index |= _buf.front();
+ _buf.pop_front();
+ _has_i_sample = false;
+ }
+
+ if (_has_i_sample)
+ continue;
+
+ // convert samples to gr_complex type by using the lookup table
+ *out++ = _lut[index];
+
+ items_left--;
+ }
+
+ return noutput_items;
+}
+
+double rtl_source_c::set_center_freq(double freq)
+{
+ if (_dev) {
+ rtlsdr_set_center_freq( _dev, (unsigned int)freq );
+ return (double)rtlsdr_get_center_freq( _dev );
+ }
+
+ return 0;
+}
+
+double rtl_source_c::set_sample_rate( double rate )
+{
+ if (_dev) {
+ rtlsdr_set_sample_rate( _dev, (unsigned int)rate );
+ return (double)rtlsdr_get_sample_rate( _dev );
+ }
+
+ return 0;
+}
+
+double rtl_source_c::get_sample_rate()
+{
+ if (_dev)
+ return (double) rtlsdr_get_sample_rate( _dev );
+
+ return 0;
+}
+
+double rtl_source_c::set_gain( double gain )
+{
+ if (_dev) {
+ rtlsdr_set_tuner_gain( _dev, (unsigned int)gain );
+ return (double)rtlsdr_get_tuner_gain( _dev );
+ }
+
+ return 0;
+}
diff --git a/lib/rtl_source_c.h b/lib/rtl_source_c.h
new file mode 100644
index 0000000..bd3dedd
--- /dev/null
+++ b/lib/rtl_source_c.h
@@ -0,0 +1,104 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012 Dimitri Stolnikov <horiz0n@gmx.net>
+ *
+ * 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.
+ */
+#ifndef INCLUDED_RTLSDR_SOURCE_C_H
+#define INCLUDED_RTLSDR_SOURCE_C_H
+
+#include <osmosdr_api.h>
+#include <gr_sync_block.h>
+#include <gruel/thread.h>
+#include <boost/circular_buffer.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+
+class rtl_source_c;
+typedef struct rtlsdr_dev rtlsdr_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<rtl_source_c> rtl_source_c_sptr;
+
+/*!
+ * \brief Return a shared_ptr to a new instance of rtl_source_c.
+ *
+ * To avoid accidental use of raw pointers, rtl_source_c's
+ * constructor is private. make_rtl_source_c is the public
+ * interface for creating new instances.
+ */
+OSMOSDR_API rtl_source_c_sptr make_rtl_source_c (const std::string & args = "");
+
+/*!
+ * \brief Provides a stream of complex samples.
+ * \ingroup block
+ *
+ */
+class OSMOSDR_API rtl_source_c : public gr_sync_block
+{
+private:
+ // The friend declaration allows make_rtl_source_c to
+ // access the private constructor.
+
+ friend OSMOSDR_API rtl_source_c_sptr make_rtl_source_c (const std::string & args);
+
+ /*!
+ * \brief Provides a stream of complex samples.
+ */
+ rtl_source_c (const std::string & args); // private constructor
+
+public:
+ ~rtl_source_c (); // public destructor
+
+ int work( int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items );
+
+ double set_center_freq( double freq );
+ double set_sample_rate( double rate );
+ double get_sample_rate();
+ double set_gain( double gain );
+
+private:
+ static void _rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx);
+ void rtlsdr_callback(unsigned char *buf, uint32_t len);
+ static void _rtlsdr_wait(rtl_source_c *obj);
+ void rtlsdr_wait();
+
+ std::vector<gr_complex> _lut;
+
+ rtlsdr_dev_t *_dev;
+ gruel::thread _thread;
+ boost::circular_buffer<unsigned char> _buf;
+ boost::mutex _buf_mutex;
+ boost::condition_variable _buf_cond;
+ bool _has_i_sample;
+};
+
+#endif /* INCLUDED_RTLSDR_SOURCE_C_H */