bladerf: migration to async api (WIP)

receive works, transmit locks up in work() after few seconds
This commit is contained in:
Dimitri Stolnikov 2013-09-20 21:41:15 +02:00
parent 2e9828f120
commit 1c9a793a70
6 changed files with 371 additions and 318 deletions

View File

@ -43,18 +43,12 @@
using namespace boost::assign; using namespace boost::assign;
bladerf_common::bladerf_common() : running(true) bladerf_common::bladerf_common() :
_is_running(false)
{ {
const char *env_fifo_size; const char *env_fifo_size;
size_t 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); env_fifo_size = getenv(BLADERF_FIFO_SIZE_ENV);
fifo_size = BLADERF_SAMPLE_FIFO_SIZE; 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); _fifo = new boost::circular_buffer<gr_complex>(fifo_size);
if (!this->sample_fifo) if (!_fifo)
throw std::runtime_error( std::string(__FUNCTION__) + throw std::runtime_error( std::string(__FUNCTION__) +
" has failed to allocate a sample FIFO!" ); " has failed to allocate a sample FIFO!" );
} }
bladerf_common::~bladerf_common() bladerf_common::~bladerf_common()
{ {
delete[] this->raw_sample_buf; delete _fifo;
delete this->sample_fifo;
} }
osmosdr::freq_range_t bladerf_common::freq_range() 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; 2.75, 3, 3.5, 4.375, 5, 6, 7, 10, 14;
BOOST_FOREACH( double half_bw, half_bandwidths ) BOOST_FOREACH( double half_bw, half_bandwidths )
bandwidths += osmosdr::range_t( half_bw * 2.e6 ); bandwidths += osmosdr::range_t( half_bw * 2e6 );
return bandwidths; return bandwidths;
} }
@ -129,9 +122,10 @@ std::vector< std::string > bladerf_common::devices()
n_devices = bladerf_get_device_list(&devices); n_devices = bladerf_get_device_list(&devices);
if (n_devices > 0) { if (n_devices > 0)
for (ssize_t i = 0; i < n_devices; i++) { {
for (ssize_t i = 0; i < n_devices; i++)
{
std::stringstream s; std::stringstream s;
std::string serial(devices[i].serial); std::string serial(devices[i].serial);
@ -154,12 +148,14 @@ std::vector< std::string > bladerf_common::devices()
bool bladerf_common::is_running() bool bladerf_common::is_running()
{ {
boost::shared_lock<boost::shared_mutex> lock(this->state_lock); boost::shared_lock<boost::shared_mutex> lock(_state_lock);
return this->running;
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); boost::unique_lock<boost::shared_mutex> lock(_state_lock);
this->running = is_running;
_is_running = is_running;
} }

View File

@ -30,6 +30,7 @@
#include <boost/thread/condition_variable.hpp> #include <boost/thread/condition_variable.hpp>
#include <gr_complex.h> #include <gr_complex.h>
#include <gruel/thread.h>
#include <libbladeRF.h> #include <libbladeRF.h>
@ -52,7 +53,7 @@ class bladerf_common
{ {
public: public:
bladerf_common(); bladerf_common();
~bladerf_common(); virtual ~bladerf_common();
protected: protected:
osmosdr::freq_range_t freq_range(); osmosdr::freq_range_t freq_range();
@ -64,15 +65,24 @@ protected:
bool is_running(); bool is_running();
void set_running(bool is_running); void set_running(bool is_running);
bladerf *dev; bladerf *_dev;
int16_t *raw_sample_buf; void **_buffers;
boost::circular_buffer<gr_complex> *sample_fifo; struct bladerf_stream *_stream;
boost::mutex sample_fifo_lock; size_t _num_buffers;
boost::condition_variable samples_available; size_t _buf_index;
gruel::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: private:
bool running; bool _is_running;
boost::shared_mutex state_lock; boost::shared_mutex _state_lock;
}; };
#endif #endif

View File

@ -96,73 +96,83 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number); device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number);
/* Open a handle to the device */ /* 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 ) { if ( ret != 0 ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to open bladeRF device " + device_name ); "failed to open bladeRF device " + device_name );
} }
if (dict.count("fw"))
{
std::string fw = dict["fw"];
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_flash_firmware has failed with " << ret << std::endl;
else
std::cerr << "The firmware has been successfully flashed." << std::endl;
}
if (dict.count("fpga")) if (dict.count("fpga"))
{ {
std::string fpga = dict["fpga"]; std::string fpga = dict["fpga"];
std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl; std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
ret = bladerf_load_fpga( this->dev, fpga.c_str() ); ret = bladerf_load_fpga( _dev, fpga.c_str() );
if ( ret != 0 ) if ( ret != 0 && ret != 1 )
std::cerr << "bladerf_load_fpga has returned with " << ret << std::endl; std::cerr << "bladerf_load_fpga has failed with " << ret << std::endl;
else else
std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl; std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl;
} }
if (dict.count("fw"))
{
std::string fw = dict["fw"];
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;
else
std::cerr << "The firmare has been successfully flashed, "
<< "please power cycle the bladeRF before using it."
<< std::endl;
}
std::cerr << "Using nuand LLC bladeRF #" << device_number; std::cerr << "Using nuand LLC bladeRF #" << device_number;
char serial[33]; char serial[BLADERF_SERIAL_LENGTH];
if ( bladerf_get_serial( this->dev, serial ) == 0 ) if ( bladerf_get_serial( _dev, serial ) == 0 )
std::cerr << " SN " << serial; std::cerr << " SN " << serial;
unsigned int major, minor; 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; 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 << " FPGA v" << major << "." << minor;
std::cerr << std::endl; 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! " std::ostringstream oss;
<< "Use the device argument fpga=/path/to/the/bitstream.rbf to load it." oss << "The FPGA is not configured! "
<< std::endl; << "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] */ /* 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] */ /* 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 );
ret = bladerf_enable_module(this->dev, BLADERF_MODULE_TX, true); _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 ) 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 = gruel::thread(write_task_dispatch, this); ret = bladerf_enable_module( _dev, BLADERF_MODULE_TX, true );
if ( ret != 0 )
std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
_thread = gruel::thread( boost::bind(&bladerf_sink_c::write_task, this) );
} }
/* /*
@ -172,78 +182,89 @@ bladerf_sink_c::~bladerf_sink_c ()
{ {
int ret; int ret;
this->set_running(false); set_running(false);
this->thread.join(); _thread.join();
ret = bladerf_enable_module(this->dev, BLADERF_MODULE_TX, false); ret = bladerf_enable_module( _dev, BLADERF_MODULE_TX, false );
if ( ret != 0 ) 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 */ /* 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 );
}
/* Convert & push samples to the sample fifo */
void *bladerf_sink_c::stream_task( void *samples, size_t num_samples )
{
size_t i, n_avail;
void *ret;
ret = _buffers[_buf_index];
_buf_index = (_buf_index + 1) % _num_buffers;
while ( is_running() )
{
{
/* Lock the circular buffer */
boost::unique_lock<boost::mutex> lock(_fifo_lock);
/* Check to make sure we have samples available */
n_avail = _fifo->size();
while( n_avail < num_samples ) {
/* Wait until there is at least a block size of samples ready */
_samp_avail.wait(lock);
n_avail = _fifo->size();
}
/* Pop samples from circular buffer, write samples to outgoing buffer */
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 ... */
/* Notify that we've just popped some samples */
//std::cerr << "-" << std::flush;
_samp_avail.notify_one();
}
return ret;
} }
void bladerf_sink_c::write_task() void bladerf_sink_c::write_task()
{ {
int i, n_samples_avail, n_samples; int status;
int16_t *p;
gr_complex sample;
while ( this->is_running() ) set_running( true );
{
{ /* Start stream and stay there until we kill the stream */
/* Lock the circular buffer */ status = bladerf_stream(_stream, BLADERF_MODULE_TX);
boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock);
/* Check to make sure we have samples available */ if (status < 0)
n_samples_avail = this->sample_fifo->size(); std::cerr << "Sink stream error: " << bladerf_strerror(status) << std::endl;
while( n_samples_avail < BLADERF_SAMPLE_BLOCK_SIZE ) {
/* Wait until there is at least a block size of samples ready */
this->samples_available.wait(lock);
n_samples_avail = this->sample_fifo->size();
}
/* Pop samples from circular buffer, write samples to outgoing buffer */ set_running( false );
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();
*p++ = 0xa000 | (int16_t)(real(sample)*2000);
*p++ = 0x5000 | (int16_t)(imag(sample)*2000);
}
} /* 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;
}
}
}
}
} }
int bladerf_sink_c::work( int noutput_items, int bladerf_sink_c::work( int noutput_items,
@ -253,44 +274,43 @@ int bladerf_sink_c::work( int noutput_items,
int n_space_avail, to_copy, limit, i; int n_space_avail, to_copy, limit, i;
const gr_complex *in = (const gr_complex *) input_items[0]; const gr_complex *in = (const gr_complex *) input_items[0];
if ( ! this->is_running() ) if ( ! is_running() )
return WORK_DONE; return WORK_DONE;
if( noutput_items >= 0 ) { /* Total samples we want to process */
/* Total samples we want to process */ to_copy = noutput_items;
to_copy = noutput_items;
/* While there are still samples to copy out ... */ /* While there are still samples to copy out ... */
while( to_copy > 0 ) { while( to_copy > 0 ) {
{ {
/* Acquire the circular buffer lock */ /* Acquire the circular buffer lock */
boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock); boost::unique_lock<boost::mutex> lock(_fifo_lock);
/* Check to see how much space is available */ /* Check to see how much space is available */
n_space_avail = this->sample_fifo->capacity() - this->sample_fifo->size(); n_space_avail = _fifo->capacity() - _fifo->size();
while (n_space_avail == 0) { while (n_space_avail == 0) {
this->samples_available.wait(lock); _samp_avail.wait(lock);
n_space_avail = this->sample_fifo->capacity() - this->sample_fifo->size(); n_space_avail = _fifo->capacity() - _fifo->size();
} }
/* Limit ourselves to either the number of output items ... /* Limit ourselves to either the number of output items ...
... or whatever space is available */ ... or whatever space is available */
limit = (n_space_avail < noutput_items ? n_space_avail : noutput_items); limit = (n_space_avail < noutput_items ? n_space_avail : noutput_items);
/* Consume! */ /* Consume! */
for( i = 0; i < limit; i++ ) { for( i = 0; i < limit; i++ ) {
this->sample_fifo->push_back(*in++); _fifo->push_back(*in++);
} }
/* Decrement the amount we need to copy */ /* Decrement the amount we need to copy */
to_copy -= limit; to_copy -= limit;
} /* Unlock by leaving the scope */ } /* Unlock by leaving the scope */
/* Notify that we've just added some samples */ /* Notify that we've just added some samples */
this->samples_available.notify_one(); //std::cerr << "+" << std::flush;
} _samp_avail.notify_one();
} }
return noutput_items; return noutput_items;
@ -309,7 +329,7 @@ size_t bladerf_sink_c::get_num_channels()
osmosdr::meta_range_t bladerf_sink_c::get_sample_rates() 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) double bladerf_sink_c::set_sample_rate(double rate)
@ -321,7 +341,7 @@ double bladerf_sink_c::set_sample_rate(double rate)
/* Check to see if the sample rate is an integer */ /* Check to see if the sample rate is an integer */
if( (uint32_t)round(rate) == (uint32_t)rate ) 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set integer rate, error " + "has failed to set integer rate, error " +
@ -329,7 +349,7 @@ double bladerf_sink_c::set_sample_rate(double rate)
} }
} else { } else {
/* TODO: Fractional sample rate */ /* 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set fractional rate, error " + "has failed to set fractional rate, error " +
@ -345,7 +365,7 @@ double bladerf_sink_c::get_sample_rate()
int ret; int ret;
unsigned int rate = 0; 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to get sample rate, error " + "has failed to get sample rate, error " +
@ -357,7 +377,7 @@ double bladerf_sink_c::get_sample_rate()
osmosdr::freq_range_t bladerf_sink_c::get_freq_range( size_t chan ) 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 ) double bladerf_sink_c::set_center_freq( double freq, size_t chan )
@ -369,7 +389,7 @@ double bladerf_sink_c::set_center_freq( double freq, size_t chan )
freq > get_freq_range( chan ).stop() ) { freq > get_freq_range( chan ).stop() ) {
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl; std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
} else { } 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to set center frequency " + "failed to set center frequency " +
@ -387,7 +407,7 @@ double bladerf_sink_c::get_center_freq( size_t chan )
uint32_t freq; uint32_t freq;
int ret; int ret;
ret = bladerf_get_frequency( this->dev, BLADERF_MODULE_TX, &freq ); ret = bladerf_get_frequency( _dev, BLADERF_MODULE_TX, &freq );
if( ret ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to get center frequency, error " + "failed to get center frequency, error " +
@ -430,9 +450,9 @@ osmosdr::gain_range_t bladerf_sink_c::get_gain_range( const std::string & name,
osmosdr::gain_range_t range; osmosdr::gain_range_t range;
if( name == "VGA1" ) { if( name == "VGA1" ) {
range = this->vga1_range; range = _vga1_range;
} else if( name == "VGA2" ) { } else if( name == "VGA2" ) {
range = this->vga2_range; range = _vga2_range;
} else { } else {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested an invalid gain element " + name ); "requested an invalid gain element " + name );
@ -461,9 +481,9 @@ double bladerf_sink_c::set_gain( double gain, const std::string & name, size_t c
int ret = 0; int ret = 0;
if( name == "VGA1" ) { if( name == "VGA1" ) {
ret = bladerf_set_txvga1( this->dev, (int)gain ); ret = bladerf_set_txvga1( _dev, (int)gain );
} else if( name == "VGA2" ) { } else if( name == "VGA2" ) {
ret = bladerf_set_txvga2( this->dev, (int)gain ); ret = bladerf_set_txvga2( _dev, (int)gain );
} else { } else {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to set the gain " "requested to set the gain "
@ -491,9 +511,9 @@ double bladerf_sink_c::get_gain( const std::string & name, size_t chan )
int ret = 0; int ret = 0;
if( name == "VGA1" ) { if( name == "VGA1" ) {
ret = bladerf_get_txvga1( this->dev, &g ); ret = bladerf_get_txvga1( _dev, &g );
} else if( name == "VGA2" ) { } else if( name == "VGA2" ) {
ret = bladerf_get_txvga2( this->dev, &g ); ret = bladerf_get_txvga2( _dev, &g );
} else { } else {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to get the gain " "requested to get the gain "
@ -546,14 +566,14 @@ double bladerf_sink_c::set_bandwidth( double bandwidth, size_t chan )
int ret; int ret;
uint32_t actual; 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not set bandwidth, error " + "could not set bandwidth, error " +
boost::lexical_cast<std::string>(ret) ); boost::lexical_cast<std::string>(ret) );
} }
return this->get_bandwidth(); return get_bandwidth();
} }
double bladerf_sink_c::get_bandwidth( size_t chan ) double bladerf_sink_c::get_bandwidth( size_t chan )
@ -561,7 +581,7 @@ double bladerf_sink_c::get_bandwidth( size_t chan )
uint32_t bandwidth; uint32_t bandwidth;
int ret; int ret;
ret = bladerf_get_bandwidth( this->dev, BLADERF_MODULE_TX, &bandwidth ); ret = bladerf_get_bandwidth( _dev, BLADERF_MODULE_TX, &bandwidth );
if( ret ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not get bandwidth, error " + "could not get bandwidth, error " +
@ -573,5 +593,5 @@ double bladerf_sink_c::get_bandwidth( size_t chan )
osmosdr::freq_range_t bladerf_sink_c::get_bandwidth_range( size_t chan ) osmosdr::freq_range_t bladerf_sink_c::get_bandwidth_range( size_t chan )
{ {
return this->filter_bandwidths(); return filter_bandwidths();
} }

View File

@ -25,10 +25,9 @@
#include <gr_block.h> #include <gr_block.h>
#include <gr_sync_block.h> #include <gr_sync_block.h>
#include <libbladeRF.h>
#include "osmosdr/osmosdr_ranges.h" #include "osmosdr/osmosdr_ranges.h"
#include "osmosdr_snk_iface.h" #include "osmosdr_snk_iface.h"
#include "bladerf_common.h" #include "bladerf_common.h"
class bladerf_sink_c; class bladerf_sink_c;
@ -108,13 +107,20 @@ public:
double get_bandwidth( size_t chan = 0 ); double get_bandwidth( size_t chan = 0 );
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 ); osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
private: private: /* functions */
static void write_task_dispatch(bladerf_sink_c *obj); 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(); void write_task();
gruel::thread thread; private: /* members */
osmosdr::gain_range_t vga1_range;
osmosdr::gain_range_t vga2_range;
}; };
#endif /* INCLUDED_BLADERF_SINK_C_H */ #endif /* INCLUDED_BLADERF_SINK_C_H */

View File

@ -96,83 +96,72 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number); device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number);
/* Open a handle to the device */ /* Open a handle to the device */
ret = bladerf_open( &this->dev, NULL ); ret = bladerf_open( &_dev, device_name.c_str() );
if ( ret != 0 ) { if ( ret != 0 ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to open bladeRF device " + device_name ); "failed to open bladeRF device " + device_name );
} }
if (dict.count("fw"))
{
std::string fw = dict["fw"];
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_flash_firmware has failed with " << ret << std::endl;
else
std::cerr << "The firmware has been successfully flashed." << std::endl;
}
if (dict.count("fpga")) if (dict.count("fpga"))
{ {
std::string fpga = dict["fpga"]; std::string fpga = dict["fpga"];
std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl; std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
ret = bladerf_load_fpga( this->dev, fpga.c_str() ); ret = bladerf_load_fpga( _dev, fpga.c_str() );
if ( ret != 0 ) if ( ret != 0 && ret != 1 )
std::cerr << "bladerf_load_fpga has returned with " << ret << std::endl; std::cerr << "bladerf_load_fpga has failed with " << ret << std::endl;
else else
std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl; std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl;
} }
if (dict.count("fw"))
{
std::string fw = dict["fw"];
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;
else
std::cerr << "The firmare has been successfully flashed, "
<< "please power cycle the bladeRF before using it."
<< std::endl;
}
std::cerr << "Using nuand LLC bladeRF #" << device_number; std::cerr << "Using nuand LLC bladeRF #" << device_number;
char serial[33]; char serial[BLADERF_SERIAL_LENGTH];
if ( bladerf_get_serial( this->dev, serial ) == 0 ) if ( bladerf_get_serial( _dev, serial ) == 0 )
std::cerr << " SN " << serial; std::cerr << " SN " << serial;
unsigned int major, minor; 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; 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 << " FPGA v" << major << "." << minor;
std::cerr << std::endl; 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! " std::ostringstream oss;
<< "Use the device argument fpga=/path/to/the/bitstream.rbf to load it." oss << "The FPGA is not configured! "
<< std::endl; << "Provide device argument fpga=/path/to/the/bitstream.rbf to load it.";
throw std::runtime_error( oss.str() );
} }
/* 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 );
if (dict.count("sampling")) if (dict.count("sampling"))
{ {
std::string sampling = dict["sampling"]; std::string sampling = dict["sampling"];
std::cerr << "Setting bladerf sampling to " << sampling << std::endl; std::cerr << "Setting bladerf sampling to " << sampling << std::endl;
if( sampling == "internal") { if( sampling == "internal") {
ret = bladerf_set_sampling( this->dev, BLADERF_SAMPLING_INTERNAL ); ret = bladerf_set_sampling( _dev, BLADERF_SAMPLING_INTERNAL );
if ( ret != 0 ) if ( ret != 0 )
std::cerr << "Problem while setting sampling mode " << ret << std::endl; std::cerr << "Problem while setting sampling mode " << ret << std::endl;
} else if( sampling == "external" ) { } else if( sampling == "external" ) {
ret = bladerf_set_sampling( this->dev, BLADERF_SAMPLING_EXTERNAL ); ret = bladerf_set_sampling( _dev, BLADERF_SAMPLING_EXTERNAL );
if ( ret != 0 ) if ( ret != 0 )
std::cerr << "Problem while setting sampling mode " << ret << std::endl; std::cerr << "Problem while setting sampling mode " << ret << std::endl;
} else { } else {
@ -180,12 +169,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 );
ret = bladerf_enable_module(this->dev, BLADERF_MODULE_RX, true); /* 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 );
/* 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 ) 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 = gruel::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 = gruel::thread( boost::bind(&bladerf_source_c::read_task, this) );
} }
/* /*
@ -195,113 +203,121 @@ bladerf_source_c::~bladerf_source_c ()
{ {
int ret; int ret;
this->set_running(false); set_running(false);
this->thread.join(); _thread.join();
ret = bladerf_enable_module(this->dev, BLADERF_MODULE_RX, false); ret = bladerf_enable_module( _dev, BLADERF_MODULE_RX, false );
if ( ret != 0 ) 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 */ /* 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 );
}
/* Convert & push samples to the sample fifo */
void *bladerf_source_c::stream_task( void *samples, size_t num_samples )
{
size_t i, n_avail, to_copy;
int16_t *sample = (int16_t *)samples;
void *ret;
ret = _buffers[_buf_index];
_buf_index = (_buf_index + 1) % _num_buffers;
_fifo_lock.lock();
n_avail = _fifo->capacity() - _fifo->size();
to_copy = (n_avail < num_samples ? n_avail : num_samples);
for(i = 0; i < to_copy; i++ ) {
/* Mask valid bits only */
*(sample) &= 0xfff;
*(sample+1) &= 0xfff;
/* Sign extend the 12-bit IQ values, if needed */
if( (*sample) & 0x800 ) *(sample) |= 0xf000;
if( *(sample+1) & 0x800 ) *(sample+1) |= 0xf000;
/* Push sample to the fifo */
_fifo->push_back( gr_complex( *sample * (1.0f/2048.0f),
*(sample+1) * (1.0f/2048.0f) ) );
/* offset to the next I+Q sample */
sample += 2;
}
_fifo_lock.unlock();
/* We have made some new samples available to the consumer in work() */
if (to_copy) {
//std::cerr << "+" << std::flush;
_samp_avail.notify_one();
}
/* Indicate overrun, if neccesary */
if (to_copy < num_samples)
std::cerr << "O" << std::flush;
return ret;
} }
void bladerf_source_c::read_task() void bladerf_source_c::read_task()
{ {
int16_t si, sq, *next_val; int status;
ssize_t n_samples;
size_t n_avail, to_copy;
while ( this->is_running() ) set_running( true );
{
n_samples = bladerf_rx(this->dev, BLADERF_FORMAT_SC16_Q12, this->raw_sample_buf, /* Start stream and stay there until we kill the stream */
BLADERF_SAMPLE_BLOCK_SIZE, NULL); status = bladerf_stream(_stream, BLADERF_MODULE_RX);
if (n_samples < 0) { if (status < 0)
std::cerr << "Failed to read samples: " std::cerr << "Source stream error: " << bladerf_strerror(status) << std::endl;
<< 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 {
//std::cerr << "+" << std::flush; set_running( false );
next_val = this->raw_sample_buf;
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);
for (size_t i = 0; i < to_copy; ++i) {
si = *next_val++ & 0xfff;
sq = *next_val++ & 0xfff;
/* Sign extend the 12-bit IQ values, if needed */
if( si & 0x800 ) si |= 0xf000;
if( sq & 0x800 ) sq |= 0xf000;
gr_complex sample((float)si * (1.0f/2048.0f),
(float)sq * (1.0f/2048.0f));
this->sample_fifo->push_back(sample);
}
this->sample_fifo_lock.unlock();
/* We have made some new samples available to the consumer in work() */
if (to_copy) {
this->samples_available.notify_one();
}
/* Indicate overrun, if neccesary */
if (to_copy < (size_t)n_samples) {
std::cerr << "O" << std::flush;
}
}
}
}
} }
/* 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, int bladerf_source_c::work( int noutput_items,
gr_vector_const_void_star &input_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items ) gr_vector_void_star &output_items )
{ {
int n_samples_avail; if ( ! is_running() )
if ( ! this->is_running() )
return WORK_DONE; return WORK_DONE;
if( noutput_items >= 0 ) { if( noutput_items > 0 ) {
gr_complex *out = (gr_complex *)output_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 */ /* 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) { while (n_samples_avail < noutput_items) {
this->samples_available.wait(lock); _samp_avail.wait(lock);
n_samples_avail = this->sample_fifo->size(); n_samples_avail = _fifo->size();
} }
for(int i = 0; i < noutput_items; ++i) { for(int i = 0; i < noutput_items; ++i) {
out[i] = this->sample_fifo->at(0); out[i] = _fifo->at(0);
this->sample_fifo->pop_front(); _fifo->pop_front();
} }
//std::cerr << "-" << std::flush; //std::cerr << "-" << std::flush;
@ -323,7 +339,7 @@ size_t bladerf_source_c::get_num_channels()
osmosdr::meta_range_t bladerf_source_c::get_sample_rates() 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 ) double bladerf_source_c::set_sample_rate( double rate )
@ -335,7 +351,7 @@ double bladerf_source_c::set_sample_rate( double rate )
/* Check to see if the sample rate is an integer */ /* Check to see if the sample rate is an integer */
if( (uint32_t)round(rate) == (uint32_t)rate ) 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set integer rate, error " + "has failed to set integer rate, error " +
@ -343,7 +359,7 @@ double bladerf_source_c::set_sample_rate( double rate )
} }
} else { } else {
/* TODO: Fractional sample rate */ /* 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set fractional rate, error " + "has failed to set fractional rate, error " +
@ -359,7 +375,7 @@ double bladerf_source_c::get_sample_rate()
int ret; int ret;
unsigned int rate = 0; 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to get sample rate, error " + "has failed to get sample rate, error " +
@ -371,7 +387,7 @@ double bladerf_source_c::get_sample_rate()
osmosdr::freq_range_t bladerf_source_c::get_freq_range( size_t chan ) 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 ) double bladerf_source_c::set_center_freq( double freq, size_t chan )
@ -383,7 +399,7 @@ double bladerf_source_c::set_center_freq( double freq, size_t chan )
freq > get_freq_range( chan ).stop() ) { freq > get_freq_range( chan ).stop() ) {
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl; std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
} else { } 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to set center frequency " + "failed to set center frequency " +
@ -401,7 +417,7 @@ double bladerf_source_c::get_center_freq( size_t chan )
uint32_t freq; uint32_t freq;
int ret; int ret;
ret = bladerf_get_frequency( this->dev, BLADERF_MODULE_RX, &freq ); ret = bladerf_get_frequency( _dev, BLADERF_MODULE_RX, &freq );
if( ret ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to get center frequency, error " + "failed to get center frequency, error " +
@ -444,11 +460,11 @@ osmosdr::gain_range_t bladerf_source_c::get_gain_range( const std::string & name
osmosdr::gain_range_t range; osmosdr::gain_range_t range;
if( name == "LNA" ) { if( name == "LNA" ) {
range = this->lna_range; range = _lna_range;
} else if( name == "VGA1" ) { } else if( name == "VGA1" ) {
range = this->vga1_range; range = _vga1_range;
} else if( name == "VGA2" ) { } else if( name == "VGA2" ) {
range = this->vga2_range; range = _vga2_range;
} else { } else {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested an invalid gain element " + name ); "requested an invalid gain element " + name );
@ -492,11 +508,11 @@ double bladerf_source_c::set_gain( double gain, const std::string & name, size_t
<< "setting to LNA_MAX (6dB)" << std::endl; << "setting to LNA_MAX (6dB)" << std::endl;
g = BLADERF_LNA_GAIN_MAX; g = BLADERF_LNA_GAIN_MAX;
} }
ret = bladerf_set_lna_gain( this->dev, g ); ret = bladerf_set_lna_gain( _dev, g );
} else if( name == "VGA1" ) { } else if( name == "VGA1" ) {
ret = bladerf_set_rxvga1( this->dev, (int)gain ); ret = bladerf_set_rxvga1( _dev, (int)gain );
} else if( name == "VGA2" ) { } else if( name == "VGA2" ) {
ret = bladerf_set_rxvga2( this->dev, (int)gain ); ret = bladerf_set_rxvga2( _dev, (int)gain );
} else { } else {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to set the gain " "requested to set the gain "
@ -526,12 +542,12 @@ double bladerf_source_c::get_gain( const std::string & name, size_t chan )
if( name == "LNA" ) { if( name == "LNA" ) {
bladerf_lna_gain lna_g; 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; g = lna_g == BLADERF_LNA_GAIN_BYPASS ? 0 : lna_g == BLADERF_LNA_GAIN_MID ? 3 : 6;
} else if( name == "VGA1" ) { } else if( name == "VGA1" ) {
ret = bladerf_get_rxvga1( this->dev, &g ); ret = bladerf_get_rxvga1( _dev, &g );
} else if( name == "VGA2" ) { } else if( name == "VGA2" ) {
ret = bladerf_get_rxvga2( this->dev, &g ); ret = bladerf_get_rxvga2( _dev, &g );
} else { } else {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to get the gain " "requested to get the gain "
@ -584,14 +600,14 @@ double bladerf_source_c::set_bandwidth( double bandwidth, size_t chan )
int ret; int ret;
uint32_t actual; 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 ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not set bandwidth, error " + "could not set bandwidth, error " +
boost::lexical_cast<std::string>(ret) ); boost::lexical_cast<std::string>(ret) );
} }
return this->get_bandwidth(); return get_bandwidth();
} }
double bladerf_source_c::get_bandwidth( size_t chan ) double bladerf_source_c::get_bandwidth( size_t chan )
@ -599,7 +615,7 @@ double bladerf_source_c::get_bandwidth( size_t chan )
uint32_t bandwidth; uint32_t bandwidth;
int ret; int ret;
ret = bladerf_get_bandwidth( this->dev, BLADERF_MODULE_RX, &bandwidth ); ret = bladerf_get_bandwidth( _dev, BLADERF_MODULE_RX, &bandwidth );
if( ret ) { if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " + throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not get bandwidth, error " + "could not get bandwidth, error " +
@ -611,5 +627,5 @@ double bladerf_source_c::get_bandwidth( size_t chan )
osmosdr::freq_range_t bladerf_source_c::get_bandwidth_range( size_t chan ) osmosdr::freq_range_t bladerf_source_c::get_bandwidth_range( size_t chan )
{ {
return this->filter_bandwidths(); return filter_bandwidths();
} }

View File

@ -25,10 +25,9 @@
#include <gr_block.h> #include <gr_block.h>
#include <gr_sync_block.h> #include <gr_sync_block.h>
#include <libbladeRF.h>
#include "osmosdr/osmosdr_ranges.h" #include "osmosdr/osmosdr_ranges.h"
#include "osmosdr_src_iface.h" #include "osmosdr_src_iface.h"
#include "bladerf_common.h" #include "bladerf_common.h"
class bladerf_source_c; class bladerf_source_c;
@ -108,14 +107,20 @@ public:
double get_bandwidth( size_t chan = 0 ); double get_bandwidth( size_t chan = 0 );
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 ); osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
private: private: /* functions */
static void read_task_dispatch(bladerf_source_c *obj); 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(); void read_task();
gruel::thread thread; private: /* members */
osmosdr::gain_range_t lna_range; osmosdr::gain_range_t _lna_range;
osmosdr::gain_range_t vga1_range;
osmosdr::gain_range_t vga2_range;
}; };
#endif /* INCLUDED_BLADERF_SOURCE_C_H */ #endif /* INCLUDED_BLADERF_SOURCE_C_H */