aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bladerf/bladerf_sink_c.cc
diff options
context:
space:
mode:
authorBrian Padalino <bpadalino@gmail.com>2014-02-16 17:42:32 -0500
committerDimitri Stolnikov <horiz0n@gmx.net>2014-03-10 15:34:19 +0100
commit4e0a2c28e3399ad7a67b7a4baff5f59f4d633fca (patch)
treeee35fef472342ac1900b4841b1f5ab921fb46d5a /lib/bladerf/bladerf_sink_c.cc
parent1adf936c9422ec75f29d9f76f091138c557a970e (diff)
bladerf: Updated source/sink to use libbladeRF's sync interface
Diffstat (limited to 'lib/bladerf/bladerf_sink_c.cc')
-rw-r--r--lib/bladerf/bladerf_sink_c.cc214
1 files changed, 31 insertions, 183 deletions
diff --git a/lib/bladerf/bladerf_sink_c.cc b/lib/bladerf/bladerf_sink_c.cc
index a6abc3f..c230e41 100644
--- a/lib/bladerf/bladerf_sink_c.cc
+++ b/lib/bladerf/bladerf_sink_c.cc
@@ -42,7 +42,7 @@
using namespace boost::assign;
/*
- * Create a new instance of bladerf_source_c and return
+ * Create a new instance of bladerf_sink_c and return
* a boost shared_ptr. This is effectively the public constructor.
*/
bladerf_sink_c_sptr make_bladerf_sink_c (const std::string &args)
@@ -75,162 +75,23 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
dict_t dict = params_to_dict(args);
/* Perform src/sink agnostic initializations */
- init(dict, "source");
+ init(dict, BLADERF_MODULE_TX);
/* Set the range of VGA1, VGA1GAINT[7:0] */
_vga1_range = osmosdr::gain_range_t( -35, -4, 1 );
/* Set the range of VGA2, VGA2GAIN[4:0] */
_vga2_range = osmosdr::gain_range_t( 0, 25, 1 );
-
- _filled = new bool[_num_buffers];
- if (!_filled) {
- throw std::runtime_error( std::string(__FUNCTION__) + " " +
- "Failed to allocate _filled[]" );
- }
-}
-
-/*
- * Our virtual destructor.
- */
-bladerf_sink_c::~bladerf_sink_c ()
-{
- int ret;
-
- if( is_running() == true ) {
- std::cerr << _pfx << "Still running when destructor called!"
- << std::endl;
- stop();
- }
-
- ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, false );
- if ( ret != 0 )
- std::cerr << _pfx << "bladerf_enable_module failed:"
- << bladerf_strerror(ret) << std::endl;
-
- /* Release stream resources */
- bladerf_deinit_stream(_stream);
-
- delete[] _filled;
-}
-
-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 )
-{
- bladerf_sink_c *obj = (bladerf_sink_c *) user_data;
- return obj->get_next_buffer( samples, num_samples );
-}
-
-static size_t buffer2index(void **buffers, void *current, size_t num_buffers)
-{
- for (size_t i = 0; i < num_buffers; ++i) {
- if (static_cast<char*>(current) == static_cast<char*>(buffers[i]))
- return i;
- }
-
- throw std::runtime_error( std::string(__FUNCTION__) + " " +
- "Has hit unexpected condition");
-}
-
-/* Fetch the next full buffer to pass down to the device */
-void *bladerf_sink_c::get_next_buffer( void *samples, size_t num_samples)
-{
- void *ret;
- bool running;
-
- {
- boost::unique_lock<boost::mutex> lock(_buf_status_lock);
-
- /* Mark the incoming buffer empty and notify work() */
- if (samples) {
- size_t buffer_emptied_index = buffer2index(_buffers, samples, _num_buffers);
-
- _filled[buffer_emptied_index] = false;
- _buffer_emptied.notify_one();
- }
-
- /* Wait for our next buffer to become filled */
- while ((running = is_running()) && !_filled[_next_to_tx]) {
- _buffer_filled.wait(lock);
- }
-
- if (running) {
- ret = _buffers[_next_to_tx];
- _next_to_tx = (_next_to_tx + 1) % _num_buffers;
- } else {
- ret = NULL;
- }
- }
-
- return ret;
-}
-
-void bladerf_sink_c::write_task()
-{
- int status;
-
- /* Start stream and stay there until we kill the stream */
- set_running(true);
- status = bladerf_stream(_stream, BLADERF_MODULE_TX);
-
- if ( status < 0 ) {
- set_running(false);
- std::cerr << _pfx << "Sink stream error: "
- << bladerf_strerror(status) << std::endl;
-
- if ( status == BLADERF_ERR_TIMEOUT ) {
- std::cerr << _pfx << "Try adjusting your sample rate or the "
- << "\"buffers\", \"buflen\", and \"transfers\" parameters. "
- << std::endl;
- }
- }
}
bool bladerf_sink_c::start()
{
- int ret;
-
- /* Initialize the stream */
- ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback,
- &_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q11,
- _samples_per_buffer, _num_transfers, this );
- if ( ret != 0 ) {
- throw std::runtime_error( std::string(__FUNCTION__) + " " +
- "bladerf_init_stream failed" ) ;
- }
-
- /* Initialize buffer management */
- _buf_index = _next_to_tx = 0;
- _next_value = static_cast<int16_t*>(_buffers[0]);
- _samples_left = _samples_per_buffer;
-
- for (size_t i = 0; i < _num_buffers; ++i) {
- _filled[i] = false;
- }
-
- ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, true );
- if ( ret != 0 ) {
- throw std::runtime_error(std::string(__FUNCTION__) + " " +
- "bladerf_enable_module has failed:" + bladerf_strerror(ret) );
- }
-
- _thread = gr::thread::thread( boost::bind(&bladerf_sink_c::write_task, this) );
- while(is_running() == false) {
- /* Not quite started up just yet, so wait for a short period of time */
- boost::this_thread::sleep( boost::posix_time::milliseconds(1) );
- }
- return true;
+ return bladerf_common::start(BLADERF_MODULE_TX);
}
bool bladerf_sink_c::stop()
{
- set_running(false);
- _thread.join();
- return true;
+ return bladerf_common::stop(BLADERF_MODULE_TX);
}
int bladerf_sink_c::work( int noutput_items,
@@ -238,56 +99,43 @@ int bladerf_sink_c::work( int noutput_items,
gr_vector_void_star &output_items )
{
const gr_complex *in = (const gr_complex *) input_items[0];
- int num_samples;
- bool running = is_running();
-
- /* Total samples we want to process */
- num_samples = noutput_items;
+ struct bladerf_metadata meta;
+ const float scaling = 2000.0f;
+ int ret;
- /* While there are still samples to copy out ... */
- while (running && num_samples > 0) {
+ if (noutput_items > _conv_buf_size) {
+ void *tmp;
- while (_samples_left && num_samples) {
+ _conv_buf_size = noutput_items;
+ tmp = realloc(_conv_buf, _conv_buf_size * 2 * sizeof(int16_t));
+ if (tmp == NULL) {
+ throw std::runtime_error( std::string(__FUNCTION__) +
+ "Failed to realloc _conv_buf" );
+ }
- /* Scale and sign extend I and then Q */
- *_next_value = (int16_t)(real(*in) * 2000);
- _next_value++;
+ _conv_buf = static_cast<int16_t*>(tmp);
+ }
- *_next_value = (int16_t)(imag(*in) * 2000);
- _next_value++;
+ /* Convert floating point samples into fixed point */
+ for (int i = 0; i < 2 * noutput_items;) {
+ _conv_buf[i++] = (int16_t)(scaling * real(*in));
+ _conv_buf[i++] = (int16_t)(scaling * imag(*in++));
+ }
- /* Advance to next sample */
- in++;
- num_samples--;
- _samples_left--;
- }
+ /* Submit them to the device */
+ ret = bladerf_sync_tx(_dev.get(), static_cast<void *>(_conv_buf),
+ noutput_items, &meta, _stream_timeout_ms);
- /* Advance to the next buffer if the current one is filled */
- if (_samples_left == 0) {
- {
- boost::unique_lock<boost::mutex> lock(_buf_status_lock);
-
- _filled[_buf_index] = true;
- _buf_index = (_buf_index + 1) % _num_buffers;
- _next_value = static_cast<int16_t*>(_buffers[_buf_index]);
- _samples_left = _samples_per_buffer;
-
- /* Signal that we have filled a buffer */
- _buffer_filled.notify_one();
-
- /* Wait here if the next buffer isn't full. The callback will
- * signal us when it has freed up a buffer */
- while (_filled[_buf_index] && running) {
- _buffer_emptied.wait(lock);
- running = is_running();
- }
- }
- }
+ if ( ret != 0 ) {
+ std::cerr << _pfx << "bladerf_sync_tx error: "
+ << bladerf_strerror(ret) << std::endl;
+ return WORK_DONE;
}
- return running ? noutput_items : 0;
+ return noutput_items;
}
+
std::vector<std::string> bladerf_sink_c::get_devices()
{
return bladerf_common::devices();