aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDimitri Stolnikov <horiz0n@gmx.net>2013-09-20 21:41:15 +0200
committerDimitri Stolnikov <horiz0n@gmx.net>2013-09-28 00:07:49 +0200
commitba7188727c4862474d8584a564882cb276dc5e37 (patch)
treeeb2698ee1c9fdfd97e31598bce642921b63ba7e4 /lib
parent04b4c8b66add671c08a880843880515a78d4f033 (diff)
bladerf: migration to async api (WIP)
receive works, transmit locks up in work() after few seconds
Diffstat (limited to 'lib')
-rw-r--r--lib/bladerf/bladerf_common.cc38
-rw-r--r--lib/bladerf/bladerf_common.h26
-rw-r--r--lib/bladerf/bladerf_sink_c.cc264
-rw-r--r--lib/bladerf/bladerf_sink_c.h19
-rw-r--r--lib/bladerf/bladerf_source_c.cc272
-rw-r--r--lib/bladerf/bladerf_source_c.h20
6 files changed, 345 insertions, 294 deletions
diff --git a/lib/bladerf/bladerf_common.cc b/lib/bladerf/bladerf_common.cc
index 43b58ec..10884dd 100644
--- a/lib/bladerf/bladerf_common.cc
+++ b/lib/bladerf/bladerf_common.cc
@@ -43,18 +43,12 @@
using namespace boost::assign;
-bladerf_common::bladerf_common() : running(true)
+bladerf_common::bladerf_common() :
+ _is_running(false)
{
const char *env_fifo_size;
size_t fifo_size;
- /* 1 Sample = i,q (2 int16_t's) */
- this->raw_sample_buf = new int16_t[2 * BLADERF_SAMPLE_BLOCK_SIZE];
- if (!raw_sample_buf) {
- throw std::runtime_error( std::string(__FUNCTION__) +
- " has failed to allocate a raw sample buffer!" );
- }
-
env_fifo_size = getenv(BLADERF_FIFO_SIZE_ENV);
fifo_size = BLADERF_SAMPLE_FIFO_SIZE;
@@ -75,16 +69,15 @@ bladerf_common::bladerf_common() : running(true)
}
}
- this->sample_fifo = new boost::circular_buffer<gr_complex>(fifo_size);
- if (!this->sample_fifo)
+ _fifo = new boost::circular_buffer<gr_complex>(fifo_size);
+ if (!_fifo)
throw std::runtime_error( std::string(__FUNCTION__) +
" has failed to allocate a sample FIFO!" );
}
bladerf_common::~bladerf_common()
{
- delete[] this->raw_sample_buf;
- delete this->sample_fifo;
+ delete _fifo;
}
osmosdr::freq_range_t bladerf_common::freq_range()
@@ -116,7 +109,7 @@ osmosdr::freq_range_t bladerf_common::filter_bandwidths()
2.75, 3, 3.5, 4.375, 5, 6, 7, 10, 14;
BOOST_FOREACH( double half_bw, half_bandwidths )
- bandwidths += osmosdr::range_t( half_bw * 2.e6 );
+ bandwidths += osmosdr::range_t( half_bw * 2e6 );
return bandwidths;
}
@@ -129,9 +122,10 @@ std::vector< std::string > bladerf_common::devices()
n_devices = bladerf_get_device_list(&devices);
- if (n_devices > 0) {
- for (ssize_t i = 0; i < n_devices; i++) {
-
+ if (n_devices > 0)
+ {
+ for (ssize_t i = 0; i < n_devices; i++)
+ {
std::stringstream s;
std::string serial(devices[i].serial);
@@ -154,12 +148,14 @@ std::vector< std::string > bladerf_common::devices()
bool bladerf_common::is_running()
{
- boost::shared_lock<boost::shared_mutex> lock(this->state_lock);
- return this->running;
+ boost::shared_lock<boost::shared_mutex> lock(_state_lock);
+
+ return _is_running;
}
-void bladerf_common::set_running(bool is_running)
+void bladerf_common::set_running( bool is_running )
{
- boost::unique_lock<boost::shared_mutex> lock(this->state_lock);
- this->running = is_running;
+ boost::unique_lock<boost::shared_mutex> lock(_state_lock);
+
+ _is_running = is_running;
}
diff --git a/lib/bladerf/bladerf_common.h b/lib/bladerf/bladerf_common.h
index a8480c0..ca95850 100644
--- a/lib/bladerf/bladerf_common.h
+++ b/lib/bladerf/bladerf_common.h
@@ -29,6 +29,7 @@
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/condition_variable.hpp>
+#include <gnuradio/thread/thread.h>
#include <gnuradio/gr_complex.h>
#include <libbladeRF.h>
@@ -52,7 +53,7 @@ class bladerf_common
{
public:
bladerf_common();
- ~bladerf_common();
+ virtual ~bladerf_common();
protected:
osmosdr::freq_range_t freq_range();
@@ -64,15 +65,24 @@ protected:
bool is_running();
void set_running(bool is_running);
- bladerf *dev;
+ bladerf *_dev;
- int16_t *raw_sample_buf;
- boost::circular_buffer<gr_complex> *sample_fifo;
- boost::mutex sample_fifo_lock;
- boost::condition_variable samples_available;
+ void **_buffers;
+ struct bladerf_stream *_stream;
+ size_t _num_buffers;
+ size_t _buf_index;
+
+ gr::thread::thread _thread;
+
+ boost::circular_buffer<gr_complex> *_fifo;
+ boost::mutex _fifo_lock;
+ boost::condition_variable _samp_avail;
+
+ osmosdr::gain_range_t _vga1_range;
+ osmosdr::gain_range_t _vga2_range;
private:
- bool running;
- boost::shared_mutex state_lock;
+ bool _is_running;
+ boost::shared_mutex _state_lock;
};
#endif
diff --git a/lib/bladerf/bladerf_sink_c.cc b/lib/bladerf/bladerf_sink_c.cc
index fe63ce8..2cd59f7 100644
--- a/lib/bladerf/bladerf_sink_c.cc
+++ b/lib/bladerf/bladerf_sink_c.cc
@@ -95,73 +95,83 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number);
/* Open a handle to the device */
- ret = bladerf_open( &this->dev, device_name.c_str() );
+ ret = bladerf_open( &_dev, device_name.c_str() );
if ( ret != 0 ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to open bladeRF device " + device_name );
}
- if (dict.count("fpga"))
+ if (dict.count("fw"))
{
- std::string fpga = dict["fpga"];
+ std::string fw = dict["fw"];
- std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
- ret = bladerf_load_fpga( this->dev, fpga.c_str() );
+ std::cerr << "Flashing firmware image " << fw << "..., DO NOT INTERRUPT!"
+ << std::endl;
+ ret = bladerf_flash_firmware( _dev, fw.c_str() );
if ( ret != 0 )
- std::cerr << "bladerf_load_fpga has returned with " << ret << std::endl;
+ std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl;
else
- std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl;
+ std::cerr << "The firmware has been successfully flashed." << std::endl;
}
- if (dict.count("fw"))
+ if (dict.count("fpga"))
{
- std::string fw = dict["fw"];
+ std::string fpga = dict["fpga"];
- std::cerr << "Flashing firmware image " << fw << "..., "
- << "DO NOT INTERRUPT!"
- << std::endl;
- ret = bladerf_flash_firmware( this->dev, fw.c_str() );
- if ( ret != 0 )
- std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl;
+ std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
+ ret = bladerf_load_fpga( _dev, fpga.c_str() );
+ if ( ret != 0 && ret != 1 )
+ std::cerr << "bladerf_load_fpga has failed with " << ret << std::endl;
else
- std::cerr << "The firmare has been successfully flashed, "
- << "please power cycle the bladeRF before using it."
- << std::endl;
+ std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl;
}
std::cerr << "Using nuand LLC bladeRF #" << device_number;
- char serial[33];
- if ( bladerf_get_serial( this->dev, serial ) == 0 )
+ char serial[BLADERF_SERIAL_LENGTH];
+ if ( bladerf_get_serial( _dev, serial ) == 0 )
std::cerr << " SN " << serial;
unsigned int major, minor;
- if ( bladerf_get_fw_version( this->dev, &major, &minor) == 0 )
+ if ( bladerf_get_fw_version( _dev, &major, &minor) == 0 )
std::cerr << " FW v" << major << "." << minor;
- if ( bladerf_get_fpga_version( this->dev, &major, &minor) == 0 )
+ if ( bladerf_get_fpga_version( _dev, &major, &minor) == 0 )
std::cerr << " FPGA v" << major << "." << minor;
std::cerr << std::endl;
- if ( bladerf_is_fpga_configured( this->dev ) != 1 )
+ if ( bladerf_is_fpga_configured( _dev ) != 1 )
{
- std::cerr << "ERROR: The FPGA is not configured! "
- << "Use the device argument fpga=/path/to/the/bitstream.rbf to load it."
- << std::endl;
+ std::ostringstream oss;
+ oss << "The FPGA is not configured! "
+ << "Provide device argument fpga=/path/to/the/bitstream.rbf to load it.";
+
+ throw std::runtime_error( oss.str() );
}
/* Set the range of VGA1, VGA1GAINT[7:0] */
- this->vga1_range = osmosdr::gain_range_t( -35, -4, 1 );
+ _vga1_range = osmosdr::gain_range_t( -35, -4, 1 );
/* Set the range of VGA2, VGA2GAIN[4:0] */
- this->vga2_range = osmosdr::gain_range_t( 0, 25, 1 );
+ _vga2_range = osmosdr::gain_range_t( 0, 25, 1 );
+
+ _buf_index = 0;
+ _num_buffers = 8; /* TODO: make it an argument */
+ const size_t samp_per_buf = 1024 * 10; /* TODO: make it an argument */
+
+ /* Initialize the stream */
+ ret = bladerf_init_stream( &_stream, _dev, stream_callback,
+ &_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q12,
+ samp_per_buf, _num_buffers, this );
+ if ( ret != 0 )
+ std::cerr << "bladerf_init_stream has failed with " << ret << std::endl;
- ret = bladerf_enable_module(this->dev, BLADERF_MODULE_TX, true);
+ ret = bladerf_enable_module( _dev, BLADERF_MODULE_TX, true );
if ( ret != 0 )
- std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
+ std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
- this->thread = gr::thread::thread(write_task_dispatch, this);
+ _thread = gr::thread::thread( boost::bind(&bladerf_sink_c::write_task, this) );
}
/*
@@ -171,78 +181,89 @@ bladerf_sink_c::~bladerf_sink_c ()
{
int ret;
- this->set_running(false);
- this->thread.join();
+ set_running(false);
+ _thread.join();
- ret = bladerf_enable_module(this->dev, BLADERF_MODULE_TX, false);
+ ret = bladerf_enable_module( _dev, BLADERF_MODULE_TX, false );
if ( ret != 0 )
- std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
+ std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
+
+ /* Release stream resources */
+ bladerf_deinit_stream(_stream);
/* Close the device */
- bladerf_close( this->dev );
+ bladerf_close( _dev );
}
-void bladerf_sink_c::write_task_dispatch(bladerf_sink_c *obj)
+void *bladerf_sink_c::stream_callback( struct bladerf *dev,
+ struct bladerf_stream *stream,
+ struct bladerf_metadata *metadata,
+ void *samples,
+ size_t num_samples,
+ void *user_data )
{
- obj->write_task();
+ bladerf_sink_c *obj = (bladerf_sink_c *) user_data;
+
+ if ( ! obj->is_running() )
+ return NULL;
+
+ return obj->stream_task( samples, num_samples );
}
-void bladerf_sink_c::write_task()
+/* Convert & push samples to the sample fifo */
+void *bladerf_sink_c::stream_task( void *samples, size_t num_samples )
{
- int i, n_samples_avail, n_samples;
- int16_t *p;
- gr_complex sample;
+ size_t i, n_avail;
+ void *ret;
- while ( this->is_running() )
- {
+ ret = _buffers[_buf_index];
+ _buf_index = (_buf_index + 1) % _num_buffers;
+ while ( is_running() )
+ {
{
/* Lock the circular buffer */
- boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock);
+ boost::unique_lock<boost::mutex> lock(_fifo_lock);
/* Check to make sure we have samples available */
- n_samples_avail = this->sample_fifo->size();
- while( n_samples_avail < BLADERF_SAMPLE_BLOCK_SIZE ) {
+ n_avail = _fifo->size();
+ while( n_avail < num_samples ) {
/* Wait until there is at least a block size of samples ready */
- this->samples_available.wait(lock);
- n_samples_avail = this->sample_fifo->size();
+ _samp_avail.wait(lock);
+ n_avail = _fifo->size();
}
/* Pop samples from circular buffer, write samples to outgoing buffer */
- int16_t *p = this->raw_sample_buf;
- for( i = 0; i < BLADERF_SAMPLE_BLOCK_SIZE; ++i ) {
- sample = this->sample_fifo->at(0);
- this->sample_fifo->pop_front();
+ int16_t *p = (int16_t *) ret;
+ for( i = 0; i < num_samples; ++i ) {
+ gr_complex sample = _fifo->at(0);
+ _fifo->pop_front();
*p++ = 0xa000 | (int16_t)(real(sample)*2000);
*p++ = 0x5000 | (int16_t)(imag(sample)*2000);
}
- } /* Give up the lock by leaving the scope ...*/
+ } /* Give up the lock by leaving the scope ... */
/* Notify that we've just popped some samples */
- this->samples_available.notify_one();
-
- /* Samples are available to write out */
- n_samples = bladerf_tx(this->dev, BLADERF_FORMAT_SC16_Q12, this->raw_sample_buf,
- BLADERF_SAMPLE_BLOCK_SIZE, NULL);
-
- /* Check n_samples return value */
- if( n_samples < 0 ) {
- std::cerr << "Failed to write samples: "
- << bladerf_strerror(n_samples) << std::endl;
- this->set_running(false);
- } else {
- if(n_samples != BLADERF_SAMPLE_BLOCK_SIZE) {
- if(n_samples > BLADERF_SAMPLE_BLOCK_SIZE) {
- std::cerr << "Warning: sent bloated sample block of "
- << n_samples << " samples!" << std::endl;
- } else {
- std::cerr << "Warning: sent truncated sample block of "
- << n_samples << " samples!" << std::endl;
- }
- }
- }
-
+ //std::cerr << "-" << std::flush;
+ _samp_avail.notify_one();
}
+
+ return ret;
+}
+
+void bladerf_sink_c::write_task()
+{
+ int status;
+
+ set_running( true );
+
+ /* Start stream and stay there until we kill the stream */
+ status = bladerf_stream(_stream, BLADERF_MODULE_TX);
+
+ if (status < 0)
+ std::cerr << "Sink stream error: " << bladerf_strerror(status) << std::endl;
+
+ set_running( false );
}
int bladerf_sink_c::work( int noutput_items,
@@ -252,44 +273,43 @@ int bladerf_sink_c::work( int noutput_items,
int n_space_avail, to_copy, limit, i;
const gr_complex *in = (const gr_complex *) input_items[0];
- if ( ! this->is_running() )
+ if ( ! is_running() )
return WORK_DONE;
- if( noutput_items >= 0 ) {
- /* Total samples we want to process */
- to_copy = noutput_items;
+ /* Total samples we want to process */
+ to_copy = noutput_items;
- /* While there are still samples to copy out ... */
- while( to_copy > 0 ) {
- {
- /* Acquire the circular buffer lock */
- boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock);
+ /* While there are still samples to copy out ... */
+ while( to_copy > 0 ) {
+ {
+ /* Acquire the circular buffer lock */
+ boost::unique_lock<boost::mutex> lock(_fifo_lock);
- /* Check to see how much space is available */
- n_space_avail = this->sample_fifo->capacity() - this->sample_fifo->size();
+ /* Check to see how much space is available */
+ n_space_avail = _fifo->capacity() - _fifo->size();
- while (n_space_avail == 0) {
- this->samples_available.wait(lock);
- n_space_avail = this->sample_fifo->capacity() - this->sample_fifo->size();
- }
+ while (n_space_avail == 0) {
+ _samp_avail.wait(lock);
+ n_space_avail = _fifo->capacity() - _fifo->size();
+ }
- /* Limit ourselves to either the number of output items ...
- ... or whatever space is available */
- limit = (n_space_avail < noutput_items ? n_space_avail : noutput_items);
+ /* Limit ourselves to either the number of output items ...
+ ... or whatever space is available */
+ limit = (n_space_avail < noutput_items ? n_space_avail : noutput_items);
- /* Consume! */
- for( i = 0; i < limit; i++ ) {
- this->sample_fifo->push_back(*in++);
- }
+ /* Consume! */
+ for( i = 0; i < limit; i++ ) {
+ _fifo->push_back(*in++);
+ }
- /* Decrement the amount we need to copy */
- to_copy -= limit;
+ /* Decrement the amount we need to copy */
+ to_copy -= limit;
- } /* Unlock by leaving the scope */
+ } /* Unlock by leaving the scope */
- /* Notify that we've just added some samples */
- this->samples_available.notify_one();
- }
+ /* Notify that we've just added some samples */
+ //std::cerr << "+" << std::flush;
+ _samp_avail.notify_one();
}
return noutput_items;
@@ -308,7 +328,7 @@ size_t bladerf_sink_c::get_num_channels()
osmosdr::meta_range_t bladerf_sink_c::get_sample_rates()
{
- return this->sample_rates();
+ return sample_rates();
}
double bladerf_sink_c::set_sample_rate(double rate)
@@ -320,7 +340,7 @@ double bladerf_sink_c::set_sample_rate(double rate)
/* Check to see if the sample rate is an integer */
if( (uint32_t)round(rate) == (uint32_t)rate )
{
- ret = bladerf_set_sample_rate( this->dev, BLADERF_MODULE_TX, (uint32_t)rate, &actual );
+ ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_TX, (uint32_t)rate, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set integer rate, error " +
@@ -328,7 +348,7 @@ double bladerf_sink_c::set_sample_rate(double rate)
}
} else {
/* TODO: Fractional sample rate */
- ret = bladerf_set_sample_rate( this->dev, BLADERF_MODULE_TX, (uint32_t)rate, &actual );
+ ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_TX, (uint32_t)rate, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set fractional rate, error " +
@@ -344,7 +364,7 @@ double bladerf_sink_c::get_sample_rate()
int ret;
unsigned int rate = 0;
- ret = bladerf_get_sample_rate( this->dev, BLADERF_MODULE_TX, &rate );
+ ret = bladerf_get_sample_rate( _dev, BLADERF_MODULE_TX, &rate );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to get sample rate, error " +
@@ -356,7 +376,7 @@ double bladerf_sink_c::get_sample_rate()
osmosdr::freq_range_t bladerf_sink_c::get_freq_range( size_t chan )
{
- return this->freq_range();
+ return freq_range();
}
double bladerf_sink_c::set_center_freq( double freq, size_t chan )
@@ -368,7 +388,7 @@ double bladerf_sink_c::set_center_freq( double freq, size_t chan )
freq > get_freq_range( chan ).stop() ) {
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
} else {
- ret = bladerf_set_frequency( this->dev, BLADERF_MODULE_TX, (uint32_t)freq );
+ ret = bladerf_set_frequency( _dev, BLADERF_MODULE_TX, (uint32_t)freq );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to set center frequency " +
@@ -386,7 +406,7 @@ double bladerf_sink_c::get_center_freq( size_t chan )
uint32_t freq;
int ret;
- ret = bladerf_get_frequency( this->dev, BLADERF_MODULE_TX, &freq );
+ ret = bladerf_get_frequency( _dev, BLADERF_MODULE_TX, &freq );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to get center frequency, error " +
@@ -429,9 +449,9 @@ osmosdr::gain_range_t bladerf_sink_c::get_gain_range( const std::string & name,
osmosdr::gain_range_t range;
if( name == "VGA1" ) {
- range = this->vga1_range;
+ range = _vga1_range;
} else if( name == "VGA2" ) {
- range = this->vga2_range;
+ range = _vga2_range;
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested an invalid gain element " + name );
@@ -460,9 +480,9 @@ double bladerf_sink_c::set_gain( double gain, const std::string & name, size_t c
int ret = 0;
if( name == "VGA1" ) {
- ret = bladerf_set_txvga1( this->dev, (int)gain );
+ ret = bladerf_set_txvga1( _dev, (int)gain );
} else if( name == "VGA2" ) {
- ret = bladerf_set_txvga2( this->dev, (int)gain );
+ ret = bladerf_set_txvga2( _dev, (int)gain );
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to set the gain "
@@ -490,9 +510,9 @@ double bladerf_sink_c::get_gain( const std::string & name, size_t chan )
int ret = 0;
if( name == "VGA1" ) {
- ret = bladerf_get_txvga1( this->dev, &g );
+ ret = bladerf_get_txvga1( _dev, &g );
} else if( name == "VGA2" ) {
- ret = bladerf_get_txvga2( this->dev, &g );
+ ret = bladerf_get_txvga2( _dev, &g );
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to get the gain "
@@ -545,14 +565,14 @@ double bladerf_sink_c::set_bandwidth( double bandwidth, size_t chan )
int ret;
uint32_t actual;
- ret = bladerf_set_bandwidth( this->dev, BLADERF_MODULE_TX, (uint32_t)bandwidth, &actual );
+ ret = bladerf_set_bandwidth( _dev, BLADERF_MODULE_TX, (uint32_t)bandwidth, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not set bandwidth, error " +
boost::lexical_cast<std::string>(ret) );
}
- return this->get_bandwidth();
+ return get_bandwidth();
}
double bladerf_sink_c::get_bandwidth( size_t chan )
@@ -560,7 +580,7 @@ double bladerf_sink_c::get_bandwidth( size_t chan )
uint32_t bandwidth;
int ret;
- ret = bladerf_get_bandwidth( this->dev, BLADERF_MODULE_TX, &bandwidth );
+ ret = bladerf_get_bandwidth( _dev, BLADERF_MODULE_TX, &bandwidth );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not get bandwidth, error " +
@@ -572,5 +592,5 @@ double bladerf_sink_c::get_bandwidth( size_t chan )
osmosdr::freq_range_t bladerf_sink_c::get_bandwidth_range( size_t chan )
{
- return this->filter_bandwidths();
+ return filter_bandwidths();
}
diff --git a/lib/bladerf/bladerf_sink_c.h b/lib/bladerf/bladerf_sink_c.h
index 8db1a8e..8fa90f4 100644
--- a/lib/bladerf/bladerf_sink_c.h
+++ b/lib/bladerf/bladerf_sink_c.h
@@ -25,8 +25,6 @@
#include <gnuradio/block.h>
#include <gnuradio/sync_block.h>
-#include <libbladeRF.h>
-
#include "osmosdr/ranges.h"
#include "sink_iface.h"
#include "bladerf_common.h"
@@ -108,13 +106,20 @@ public:
double get_bandwidth( size_t chan = 0 );
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
-private:
- static void write_task_dispatch(bladerf_sink_c *obj);
+private: /* functions */
+ static void *stream_callback( struct bladerf *_dev,
+ struct bladerf_stream *stream,
+ struct bladerf_metadata *metadata,
+ void *samples,
+ size_t num_samples,
+ void *user_data );
+
+ void *stream_task(void *samples, size_t num_samples);
+
void write_task();
- gr::thread::thread thread;
- osmosdr::gain_range_t vga1_range;
- osmosdr::gain_range_t vga2_range;
+private: /* members */
+
};
#endif /* INCLUDED_BLADERF_SINK_C_H */
diff --git a/lib/bladerf/bladerf_source_c.cc b/lib/bladerf/bladerf_source_c.cc
index 99aa0e9..931e33b 100644
--- a/lib/bladerf/bladerf_source_c.cc
+++ b/lib/bladerf/bladerf_source_c.cc
@@ -95,70 +95,60 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number);
/* Open a handle to the device */
- ret = bladerf_open( &this->dev, NULL );
+ ret = bladerf_open( &_dev, device_name.c_str() );
if ( ret != 0 ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to open bladeRF device " + device_name );
}
- if (dict.count("fpga"))
+ if (dict.count("fw"))
{
- std::string fpga = dict["fpga"];
+ std::string fw = dict["fw"];
- std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
- ret = bladerf_load_fpga( this->dev, fpga.c_str() );
+ std::cerr << "Flashing firmware image " << fw << "..., DO NOT INTERRUPT!"
+ << std::endl;
+ ret = bladerf_flash_firmware( _dev, fw.c_str() );
if ( ret != 0 )
- std::cerr << "bladerf_load_fpga has returned with " << ret << std::endl;
+ std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl;
else
- std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl;
+ std::cerr << "The firmware has been successfully flashed." << std::endl;
}
- if (dict.count("fw"))
+ if (dict.count("fpga"))
{
- std::string fw = dict["fw"];
+ std::string fpga = dict["fpga"];
- std::cerr << "Flashing firmware image " << fw << "..., "
- << "DO NOT INTERRUPT!"
- << std::endl;
- ret = bladerf_flash_firmware( this->dev, fw.c_str() );
- if ( ret != 0 )
- std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl;
+ std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
+ ret = bladerf_load_fpga( _dev, fpga.c_str() );
+ if ( ret != 0 && ret != 1 )
+ std::cerr << "bladerf_load_fpga has failed with " << ret << std::endl;
else
- std::cerr << "The firmare has been successfully flashed, "
- << "please power cycle the bladeRF before using it."
- << std::endl;
+ std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl;
}
std::cerr << "Using nuand LLC bladeRF #" << device_number;
- char serial[33];
- if ( bladerf_get_serial( this->dev, serial ) == 0 )
+ char serial[BLADERF_SERIAL_LENGTH];
+ if ( bladerf_get_serial( _dev, serial ) == 0 )
std::cerr << " SN " << serial;
unsigned int major, minor;
- if ( bladerf_get_fw_version( this->dev, &major, &minor) == 0 )
+ if ( bladerf_get_fw_version( _dev, &major, &minor) == 0 )
std::cerr << " FW v" << major << "." << minor;
- if ( bladerf_get_fpga_version( this->dev, &major, &minor) == 0 )
+ if ( bladerf_get_fpga_version( _dev, &major, &minor) == 0 )
std::cerr << " FPGA v" << major << "." << minor;
std::cerr << std::endl;
- if ( bladerf_is_fpga_configured( this->dev ) != 1 )
+ if ( bladerf_is_fpga_configured( _dev ) != 1 )
{
- std::cerr << "ERROR: The FPGA is not configured! "
- << "Use the device argument fpga=/path/to/the/bitstream.rbf to load it."
- << std::endl;
- }
+ std::ostringstream oss;
+ oss << "The FPGA is not configured! "
+ << "Provide device argument fpga=/path/to/the/bitstream.rbf to load it.";
- /* Set the range of LNA, G_LNA_RXFE[1:0] */
- this->lna_range = osmosdr::gain_range_t( 0, 6, 3 );
-
- /* Set the range of VGA1, RFB_TIA_RXFE[6:0], nonlinear mapping done inside the lib */
- this->vga1_range = osmosdr::gain_range_t( 5, 30, 1 );
-
- /* Set the range of VGA2 VGA2GAIN[4:0], not recommended to be used above 30dB */
- this->vga2_range = osmosdr::gain_range_t( 0, 60, 3 );
+ throw std::runtime_error( oss.str() );
+ }
if (dict.count("sampling"))
{
@@ -166,12 +156,11 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
std::cerr << "Setting bladerf sampling to " << sampling << std::endl;
if( sampling == "internal") {
- ret = bladerf_set_sampling( this->dev, BLADERF_SAMPLING_INTERNAL );
+ ret = bladerf_set_sampling( _dev, BLADERF_SAMPLING_INTERNAL );
if ( ret != 0 )
std::cerr << "Problem while setting sampling mode " << ret << std::endl;
-
} else if( sampling == "external" ) {
- ret = bladerf_set_sampling( this->dev, BLADERF_SAMPLING_EXTERNAL );
+ ret = bladerf_set_sampling( _dev, BLADERF_SAMPLING_EXTERNAL );
if ( ret != 0 )
std::cerr << "Problem while setting sampling mode " << ret << std::endl;
} else {
@@ -179,12 +168,31 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
}
}
+ /* Set the range of LNA, G_LNA_RXFE[1:0] */
+ _lna_range = osmosdr::gain_range_t( 0, 6, 3 );
+
+ /* Set the range of VGA1, RFB_TIA_RXFE[6:0], nonlinear mapping done inside the lib */
+ _vga1_range = osmosdr::gain_range_t( 5, 30, 1 );
- ret = bladerf_enable_module(this->dev, BLADERF_MODULE_RX, true);
+ /* Set the range of VGA2 VGA2GAIN[4:0], not recommended to be used above 30dB */
+ _vga2_range = osmosdr::gain_range_t( 0, 60, 3 );
+
+ _buf_index = 0;
+ _num_buffers = 8; /* TODO: make it an argument */
+ const size_t samp_per_buf = 1024 * 10; /* TODO: make it an argument */
+
+ /* Initialize the stream */
+ ret = bladerf_init_stream( &_stream, _dev, stream_callback,
+ &_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q12,
+ samp_per_buf, _num_buffers, this );
if ( ret != 0 )
- std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
+ std::cerr << "bladerf_init_stream has failed with " << ret << std::endl;
- this->thread = gr::thread::thread(read_task_dispatch, this);
+ ret = bladerf_enable_module( _dev, BLADERF_MODULE_RX, true );
+ if ( ret != 0 )
+ std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
+
+ _thread = gr::thread::thread( boost::bind(&bladerf_source_c::read_task, this) );
}
/*
@@ -194,113 +202,121 @@ bladerf_source_c::~bladerf_source_c ()
{
int ret;
- this->set_running(false);
- this->thread.join();
+ set_running(false);
+ _thread.join();
- ret = bladerf_enable_module(this->dev, BLADERF_MODULE_RX, false);
+ ret = bladerf_enable_module( _dev, BLADERF_MODULE_RX, false );
if ( ret != 0 )
- std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
+ std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
+
+ /* Release stream resources */
+ bladerf_deinit_stream(_stream);
/* Close the device */
- bladerf_close( this->dev );
+ bladerf_close( _dev );
}
-void bladerf_source_c::read_task_dispatch(bladerf_source_c *obj)
+void *bladerf_source_c::stream_callback( struct bladerf *dev,
+ struct bladerf_stream *stream,
+ struct bladerf_metadata *metadata,
+ void *samples,
+ size_t num_samples,
+ void *user_data )
{
- obj->read_task();
+ bladerf_source_c *obj = (bladerf_source_c *) user_data;
+
+ if ( ! obj->is_running() )
+ return NULL;
+
+ return obj->stream_task( samples, num_samples );
}
-void bladerf_source_c::read_task()
+/* Convert & push samples to the sample fifo */
+void *bladerf_source_c::stream_task( void *samples, size_t num_samples )
{
- int16_t si, sq, *next_val;
- ssize_t n_samples;
- size_t n_avail, to_copy;
+ size_t i, n_avail, to_copy;
+ int16_t *sample = (int16_t *)samples;
+ void *ret;
- while ( this->is_running() )
- {
+ ret = _buffers[_buf_index];
+ _buf_index = (_buf_index + 1) % _num_buffers;
- n_samples = bladerf_rx(this->dev, BLADERF_FORMAT_SC16_Q12, this->raw_sample_buf,
- BLADERF_SAMPLE_BLOCK_SIZE, NULL);
+ _fifo_lock.lock();
- if (n_samples < 0) {
- std::cerr << "Failed to read samples: "
- << bladerf_strerror(n_samples) << std::endl;
- this->set_running(false);
- } else {
- if (n_samples != BLADERF_SAMPLE_BLOCK_SIZE) {
- if (n_samples > BLADERF_SAMPLE_BLOCK_SIZE) {
- std::cerr << "Warning: received bloated sample block of "
- << n_samples << " bytes!"<< std::endl;
- } else {
- std::cerr << "Warning: received truncated sample block of "
- << n_samples << " bytes!"<< std::endl;
- }
- } else {
+ n_avail = _fifo->capacity() - _fifo->size();
+ to_copy = (n_avail < num_samples ? n_avail : num_samples);
- //std::cerr << "+" << std::flush;
+ for(i = 0; i < to_copy; i++ ) {
+ /* Mask valid bits only */
+ *(sample) &= 0xfff;
+ *(sample+1) &= 0xfff;
- next_val = this->raw_sample_buf;
+ /* Sign extend the 12-bit IQ values, if needed */
+ if( (*sample) & 0x800 ) *(sample) |= 0xf000;
+ if( *(sample+1) & 0x800 ) *(sample+1) |= 0xf000;
- this->sample_fifo_lock.lock();
- n_avail = this->sample_fifo->capacity() - this->sample_fifo->size();
- to_copy = (n_avail < (size_t)n_samples ? n_avail : (size_t)n_samples);
+ /* Push sample to the fifo */
+ _fifo->push_back( gr_complex( *sample * (1.0f/2048.0f),
+ *(sample+1) * (1.0f/2048.0f) ) );
- for (size_t i = 0; i < to_copy; ++i) {
- si = *next_val++ & 0xfff;
- sq = *next_val++ & 0xfff;
+ /* offset to the next I+Q sample */
+ sample += 2;
+ }
- /* Sign extend the 12-bit IQ values, if needed */
- if( si & 0x800 ) si |= 0xf000;
- if( sq & 0x800 ) sq |= 0xf000;
+ _fifo_lock.unlock();
- gr_complex sample((float)si * (1.0f/2048.0f),
- (float)sq * (1.0f/2048.0f));
+ /* We have made some new samples available to the consumer in work() */
+ if (to_copy) {
+ //std::cerr << "+" << std::flush;
+ _samp_avail.notify_one();
+ }
- this->sample_fifo->push_back(sample);
- }
+ /* Indicate overrun, if neccesary */
+ if (to_copy < num_samples)
+ std::cerr << "O" << std::flush;
- this->sample_fifo_lock.unlock();
+ return ret;
+}
- /* We have made some new samples available to the consumer in work() */
- if (to_copy) {
- this->samples_available.notify_one();
- }
+void bladerf_source_c::read_task()
+{
+ int status;
- /* Indicate overrun, if neccesary */
- if (to_copy < (size_t)n_samples) {
- std::cerr << "O" << std::flush;
- }
- }
- }
+ set_running( true );
- }
+ /* Start stream and stay there until we kill the stream */
+ status = bladerf_stream(_stream, BLADERF_MODULE_RX);
+
+ if (status < 0)
+ std::cerr << "Source stream error: " << bladerf_strerror(status) << std::endl;
+
+ set_running( false );
}
-/* Main work function, pull samples from the driver */
+/* Main work function, pull samples from the sample fifo */
int bladerf_source_c::work( int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items )
{
- int n_samples_avail;
-
- if ( ! this->is_running() )
+ if ( ! is_running() )
return WORK_DONE;
- if( noutput_items >= 0 ) {
+ if( noutput_items > 0 ) {
gr_complex *out = (gr_complex *)output_items[0];
- boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock);
+
+ boost::unique_lock<boost::mutex> lock(_fifo_lock);
/* Wait until we have the requested number of samples */
- n_samples_avail = this->sample_fifo->size();
+ int n_samples_avail = _fifo->size();
while (n_samples_avail < noutput_items) {
- this->samples_available.wait(lock);
- n_samples_avail = this->sample_fifo->size();
+ _samp_avail.wait(lock);
+ n_samples_avail = _fifo->size();
}
for(int i = 0; i < noutput_items; ++i) {
- out[i] = this->sample_fifo->at(0);
- this->sample_fifo->pop_front();
+ out[i] = _fifo->at(0);
+ _fifo->pop_front();
}
//std::cerr << "-" << std::flush;
@@ -322,7 +338,7 @@ size_t bladerf_source_c::get_num_channels()
osmosdr::meta_range_t bladerf_source_c::get_sample_rates()
{
- return this->sample_rates();
+ return sample_rates();
}
double bladerf_source_c::set_sample_rate( double rate )
@@ -334,7 +350,7 @@ double bladerf_source_c::set_sample_rate( double rate )
/* Check to see if the sample rate is an integer */
if( (uint32_t)round(rate) == (uint32_t)rate )
{
- ret = bladerf_set_sample_rate( this->dev, BLADERF_MODULE_RX, (uint32_t)rate, &actual );
+ ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_RX, (uint32_t)rate, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set integer rate, error " +
@@ -342,7 +358,7 @@ double bladerf_source_c::set_sample_rate( double rate )
}
} else {
/* TODO: Fractional sample rate */
- ret = bladerf_set_sample_rate( this->dev, BLADERF_MODULE_RX, (uint32_t)rate, &actual );
+ ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_RX, (uint32_t)rate, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set fractional rate, error " +
@@ -358,7 +374,7 @@ double bladerf_source_c::get_sample_rate()
int ret;
unsigned int rate = 0;
- ret = bladerf_get_sample_rate( this->dev, BLADERF_MODULE_RX, &rate );
+ ret = bladerf_get_sample_rate( _dev, BLADERF_MODULE_RX, &rate );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to get sample rate, error " +
@@ -370,7 +386,7 @@ double bladerf_source_c::get_sample_rate()
osmosdr::freq_range_t bladerf_source_c::get_freq_range( size_t chan )
{
- return this->freq_range();
+ return freq_range();
}
double bladerf_source_c::set_center_freq( double freq, size_t chan )
@@ -382,7 +398,7 @@ double bladerf_source_c::set_center_freq( double freq, size_t chan )
freq > get_freq_range( chan ).stop() ) {
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
} else {
- ret = bladerf_set_frequency( this->dev, BLADERF_MODULE_RX, (uint32_t)freq );
+ ret = bladerf_set_frequency( _dev, BLADERF_MODULE_RX, (uint32_t)freq );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to set center frequency " +
@@ -400,7 +416,7 @@ double bladerf_source_c::get_center_freq( size_t chan )
uint32_t freq;
int ret;
- ret = bladerf_get_frequency( this->dev, BLADERF_MODULE_RX, &freq );
+ ret = bladerf_get_frequency( _dev, BLADERF_MODULE_RX, &freq );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to get center frequency, error " +
@@ -443,11 +459,11 @@ osmosdr::gain_range_t bladerf_source_c::get_gain_range( const std::string & name
osmosdr::gain_range_t range;
if( name == "LNA" ) {
- range = this->lna_range;
+ range = _lna_range;
} else if( name == "VGA1" ) {
- range = this->vga1_range;
+ range = _vga1_range;
} else if( name == "VGA2" ) {
- range = this->vga2_range;
+ range = _vga2_range;
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested an invalid gain element " + name );
@@ -491,11 +507,11 @@ double bladerf_source_c::set_gain( double gain, const std::string & name, size_t
<< "setting to LNA_MAX (6dB)" << std::endl;
g = BLADERF_LNA_GAIN_MAX;
}
- ret = bladerf_set_lna_gain( this->dev, g );
+ ret = bladerf_set_lna_gain( _dev, g );
} else if( name == "VGA1" ) {
- ret = bladerf_set_rxvga1( this->dev, (int)gain );
+ ret = bladerf_set_rxvga1( _dev, (int)gain );
} else if( name == "VGA2" ) {
- ret = bladerf_set_rxvga2( this->dev, (int)gain );
+ ret = bladerf_set_rxvga2( _dev, (int)gain );
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to set the gain "
@@ -525,12 +541,12 @@ double bladerf_source_c::get_gain( const std::string & name, size_t chan )
if( name == "LNA" ) {
bladerf_lna_gain lna_g;
- ret = bladerf_get_lna_gain( this->dev, &lna_g );
+ ret = bladerf_get_lna_gain( _dev, &lna_g );
g = lna_g == BLADERF_LNA_GAIN_BYPASS ? 0 : lna_g == BLADERF_LNA_GAIN_MID ? 3 : 6;
} else if( name == "VGA1" ) {
- ret = bladerf_get_rxvga1( this->dev, &g );
+ ret = bladerf_get_rxvga1( _dev, &g );
} else if( name == "VGA2" ) {
- ret = bladerf_get_rxvga2( this->dev, &g );
+ ret = bladerf_get_rxvga2( _dev, &g );
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to get the gain "
@@ -583,14 +599,14 @@ double bladerf_source_c::set_bandwidth( double bandwidth, size_t chan )
int ret;
uint32_t actual;
- ret = bladerf_set_bandwidth( this->dev, BLADERF_MODULE_RX, (uint32_t)bandwidth, &actual );
+ ret = bladerf_set_bandwidth( _dev, BLADERF_MODULE_RX, (uint32_t)bandwidth, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not set bandwidth, error " +
boost::lexical_cast<std::string>(ret) );
}
- return this->get_bandwidth();
+ return get_bandwidth();
}
double bladerf_source_c::get_bandwidth( size_t chan )
@@ -598,7 +614,7 @@ double bladerf_source_c::get_bandwidth( size_t chan )
uint32_t bandwidth;
int ret;
- ret = bladerf_get_bandwidth( this->dev, BLADERF_MODULE_RX, &bandwidth );
+ ret = bladerf_get_bandwidth( _dev, BLADERF_MODULE_RX, &bandwidth );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not get bandwidth, error " +
@@ -610,5 +626,5 @@ double bladerf_source_c::get_bandwidth( size_t chan )
osmosdr::freq_range_t bladerf_source_c::get_bandwidth_range( size_t chan )
{
- return this->filter_bandwidths();
+ return filter_bandwidths();
}
diff --git a/lib/bladerf/bladerf_source_c.h b/lib/bladerf/bladerf_source_c.h
index 8074ccf..e2a43ee 100644
--- a/lib/bladerf/bladerf_source_c.h
+++ b/lib/bladerf/bladerf_source_c.h
@@ -25,8 +25,6 @@
#include <gnuradio/block.h>
#include <gnuradio/sync_block.h>
-#include <libbladeRF.h>
-
#include "osmosdr/ranges.h"
#include "source_iface.h"
#include "bladerf_common.h"
@@ -108,14 +106,20 @@ public:
double get_bandwidth( size_t chan = 0 );
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
-private:
- static void read_task_dispatch(bladerf_source_c *obj);
+private: /* functions */
+ static void *stream_callback( struct bladerf *_dev,
+ struct bladerf_stream *stream,
+ struct bladerf_metadata *metadata,
+ void *samples,
+ size_t num_samples,
+ void *user_data );
+
+ void *stream_task(void *samples, size_t num_samples);
+
void read_task();
- gr::thread::thread thread;
- osmosdr::gain_range_t lna_range;
- osmosdr::gain_range_t vga1_range;
- osmosdr::gain_range_t vga2_range;
+private: /* members */
+ osmosdr::gain_range_t _lna_range;
};
#endif /* INCLUDED_BLADERF_SOURCE_C_H */