aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Szymaniak <jon.szymaniak@gmail.com>2015-06-22 17:38:03 -0400
committerDimitri Stolnikov <horiz0n@gmx.net>2015-07-17 17:09:23 +0200
commit43a00ae785ba5e9703b28e079b2ba78f7021ebb0 (patch)
treefa52d3499702d2b05406eab2ae9dfd9f7600509b
parentac1d8ec02def12a31168a1d06683c027cecdfe0e (diff)
bladeRF: Added SOB/EOB stream tag handling support to bladerf_sink
When running with metadata mode enabled, the bladerf_sink supports 'tx_sob' and 'tx_eob' stream tags. Anything not in the burst will be dropped, and a warning will be printed. Use of the bladeRF metadata can be enabled via a 'enable_metadata' device argument. If running full-duplex, this must be provided to both the source and the sink. This does not currently any additional features to the sink.
-rw-r--r--lib/bladerf/bladerf_common.cc13
-rw-r--r--lib/bladerf/bladerf_common.h2
-rw-r--r--lib/bladerf/bladerf_sink_c.cc152
-rw-r--r--lib/bladerf/bladerf_sink_c.h8
-rw-r--r--lib/bladerf/bladerf_source_c.cc10
5 files changed, 179 insertions, 6 deletions
diff --git a/lib/bladerf/bladerf_common.cc b/lib/bladerf/bladerf_common.cc
index 094de3e..191a327 100644
--- a/lib/bladerf/bladerf_common.cc
+++ b/lib/bladerf/bladerf_common.cc
@@ -190,8 +190,15 @@ void bladerf_common::set_verbosity(const std::string &verbosity)
bool bladerf_common::start(bladerf_module module)
{
int ret;
+ bladerf_format format;
- ret = bladerf_sync_config(_dev.get(), module, BLADERF_FORMAT_SC16_Q11,
+ if (_use_metadata) {
+ format = BLADERF_FORMAT_SC16_Q11_META;
+ } else {
+ format = BLADERF_FORMAT_SC16_Q11;
+ }
+
+ ret = bladerf_sync_config(_dev.get(), module, format,
_num_buffers, _samples_per_buffer,
_num_transfers, _stream_timeout_ms);
@@ -382,6 +389,8 @@ void bladerf_common::init(dict_t &dict, bladerf_module module)
_stream_timeout_ms = boost::lexical_cast< unsigned int >(dict["stream_timeout_ms"] );
}
+ _use_metadata = dict.count("enable_metadata") != 0;
+
/* Require value to be >= 2 so we can ensure we have twice as many
* buffers as transfers */
if (_num_buffers <= 1) {
@@ -429,7 +438,7 @@ void bladerf_common::init(dict_t &dict, bladerf_module module)
osmosdr::freq_range_t bladerf_common::freq_range()
{
/* assuming the same for RX & TX */
- return osmosdr::freq_range_t( _xb_200_attached ? 0 : 300e6, 3.8e9 );
+ return osmosdr::freq_range_t( _xb_200_attached ? 0 : 280e6, BLADERF_FREQUENCY_MAX );
}
osmosdr::meta_range_t bladerf_common::sample_rates()
diff --git a/lib/bladerf/bladerf_common.h b/lib/bladerf/bladerf_common.h
index d16c02f..b791003 100644
--- a/lib/bladerf/bladerf_common.h
+++ b/lib/bladerf/bladerf_common.h
@@ -83,6 +83,8 @@ protected:
int16_t *_conv_buf;
int _conv_buf_size; /* In units of samples */
+ bool _use_metadata;
+
osmosdr::gain_range_t _vga1_range;
osmosdr::gain_range_t _vga2_range;
diff --git a/lib/bladerf/bladerf_sink_c.cc b/lib/bladerf/bladerf_sink_c.cc
index 2dc2e04..fffe8dd 100644
--- a/lib/bladerf/bladerf_sink_c.cc
+++ b/lib/bladerf/bladerf_sink_c.cc
@@ -35,10 +35,19 @@
#include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h>
+#include <gnuradio/tags.h>
+#include <gnuradio/sync_block.h>
#include "arg_helpers.h"
#include "bladerf_sink_c.h"
+//#define DEBUG_BLADERF_SINK
+#ifdef DEBUG_BLADERF_SINK
+# define DBG(input) std::cerr << _pfx << input << std::endl
+#else
+# define DBG(input)
+#endif
+
using namespace boost::assign;
/*
@@ -82,10 +91,12 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
/* Set the range of VGA2, VGA2GAIN[4:0] */
_vga2_range = osmosdr::gain_range_t( 0, 25, 1 );
+
}
bool bladerf_sink_c::start()
{
+ _in_burst = false;
return bladerf_common::start(BLADERF_MODULE_TX);
}
@@ -94,6 +105,136 @@ bool bladerf_sink_c::stop()
return bladerf_common::stop(BLADERF_MODULE_TX);
}
+#define INVALID_IDX -1
+
+int bladerf_sink_c::transmit_with_tags(int noutput_items)
+{
+ int count = 0;
+ int status = 0;
+
+ // For a long burst, we may be transmitting the burst contents over
+ // multiple work calls, so we'll just be sending the entire buffer
+ // Therefore, we initialize our indicies for this case.
+ int start_idx = 0;
+ int end_idx = (noutput_items - 1);
+
+ struct bladerf_metadata meta;
+ std::vector<gr::tag_t> tags;
+
+ int16_t zeros[8] = { 0 };
+
+ memset(&meta, 0, sizeof(meta));
+
+ DBG("transmit_with_tags(" << noutput_items << ")");
+
+ // Important Note: We assume that these tags are ordered by their offsets.
+ // This is true for GNU Radio 3.7.7.x, since the GR runtime libs store
+ // these in a multimap.
+ //
+ // If you're using an earlier GNU Radio version, you may have to sort
+ // the tags vector.
+ get_tags_in_window(tags, 0, 0, noutput_items);
+
+ if (tags.size() == 0) {
+ if (_in_burst) {
+ DBG("TX'ing " << noutput_items << " samples in within a burst...");
+
+ return bladerf_sync_tx(_dev.get(),
+ static_cast<void *>(_conv_buf),
+ noutput_items, &meta, _stream_timeout_ms);
+ } else {
+ std::cerr << _pfx << "Dropping " << noutput_items
+ << " samples not in a burst." << std::endl;
+ }
+ }
+
+
+ BOOST_FOREACH( gr::tag_t tag, tags) {
+
+ // Upon seeing an SOB tag, update our offset. We'll TX the start of the
+ // burst when we see an EOB or at the end of this function - whichever
+ // occurs first.
+ if (pmt::symbol_to_string(tag.key) == "tx_sob") {
+ if (_in_burst) {
+ std::cerr << ("Got SOB while already within a burst");
+ return BLADERF_ERR_INVAL;
+ } else {
+ start_idx = static_cast<int>(tag.offset - nitems_read(0));
+ DBG("Got SOB " << start_idx << " samples into work payload");
+
+ meta.flags |= (BLADERF_META_FLAG_TX_NOW | BLADERF_META_FLAG_TX_BURST_START);
+ _in_burst = true;
+
+ }
+ } else if (pmt::symbol_to_string(tag.key) == "tx_eob") {
+ if (!_in_burst) {
+ std::cerr << _pfx << "Got EOB while not in burst" << std::endl;
+ return BLADERF_ERR_INVAL;
+ }
+
+ // Upon seeing an EOB, transmit what we have and reset our state
+ end_idx = static_cast<int>(tag.offset - nitems_read(0));
+ DBG("Got EOB " << end_idx << " samples into work payload");
+
+ if ( (start_idx == INVALID_IDX) || (start_idx > end_idx) ) {
+ DBG("Buffer indicies are in an invalid state!");
+ return BLADERF_ERR_INVAL;
+ }
+
+ count = end_idx - start_idx + 1;
+
+ DBG("TXing @ EOB [" << start_idx << ":" << end_idx << "]");
+
+ status = bladerf_sync_tx(_dev.get(),
+ static_cast<void *>(&_conv_buf[2*start_idx]),
+ count, &meta, _stream_timeout_ms);
+ if (status != 0) {
+ return status;
+ }
+
+ /* TODO: libbladeRF should now take care of this for us,
+ * as of the libbladeRF version that includes the
+ * TX_UPDATE_TIMESTAMP flag. Verify this potentially remove this.
+ * (The meta.flags changes would then be applied to the previous
+ * bladerf_sync_tx() call.)
+ */
+ DBG("TXing Zeros with burst end flag");
+
+ meta.flags &= ~(BLADERF_META_FLAG_TX_NOW | BLADERF_META_FLAG_TX_BURST_START);
+ meta.flags |= BLADERF_META_FLAG_TX_BURST_END;
+
+ status = bladerf_sync_tx(_dev.get(),
+ static_cast<void *>(zeros),
+ 4, &meta, _stream_timeout_ms);
+
+
+ /* Reset our state */
+ start_idx = INVALID_IDX;
+ end_idx = (noutput_items - 1);
+ meta.flags = 0;
+ _in_burst = false;
+
+ if (status != 0) {
+ DBG("Failed to send zero samples to flush EOB");
+ return status;
+ }
+ }
+ }
+
+ // We had a start of burst with no end yet - transmit those samples
+ if (_in_burst) {
+ count = end_idx - start_idx + 1;
+
+ DBG("TXing SOB [" << start_idx << ":" << end_idx << "]");
+
+ status = bladerf_sync_tx(_dev.get(),
+ static_cast<void *>(&_conv_buf[2*start_idx]),
+ count, &meta, _stream_timeout_ms);
+ }
+
+ return status;
+}
+
int bladerf_sink_c::work( int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items )
@@ -110,6 +251,8 @@ int bladerf_sink_c::work( int noutput_items,
if (tmp == NULL) {
throw std::runtime_error( std::string(__FUNCTION__) +
"Failed to realloc _conv_buf" );
+ } else {
+ DBG("Resized _conv_buf to " << _conv_buf_size << " samples");
}
_conv_buf = static_cast<int16_t*>(tmp);
@@ -121,9 +264,12 @@ int bladerf_sink_c::work( int noutput_items,
_conv_buf[i++] = (int16_t)(scaling * imag(*in++));
}
- /* Submit them to the device */
- ret = bladerf_sync_tx(_dev.get(), static_cast<void *>(_conv_buf),
- noutput_items, NULL, _stream_timeout_ms);
+ if (_use_metadata) {
+ ret = transmit_with_tags(noutput_items);
+ } else {
+ ret = bladerf_sync_tx(_dev.get(), static_cast<void *>(_conv_buf),
+ noutput_items, NULL, _stream_timeout_ms);
+ }
if ( ret != 0 ) {
std::cerr << _pfx << "bladerf_sync_tx error: "
diff --git a/lib/bladerf/bladerf_sink_c.h b/lib/bladerf/bladerf_sink_c.h
index 6b2cb00..57d174b 100644
--- a/lib/bladerf/bladerf_sink_c.h
+++ b/lib/bladerf/bladerf_sink_c.h
@@ -65,6 +65,14 @@ private:
bladerf_sink_c (const std::string & args); // private constructor
+ // Transmit converted samples stored in _conv_buf, applying SOB and EOB
+ // based upon the provided tags
+ //
+ // Returns bladeRF error code
+ int transmit_with_tags(int noutput_items);
+
+ bool _in_burst;
+
public:
bool start();
bool stop();
diff --git a/lib/bladerf/bladerf_source_c.cc b/lib/bladerf/bladerf_source_c.cc
index 7450b1b..b4afcb2 100644
--- a/lib/bladerf/bladerf_source_c.cc
+++ b/lib/bladerf/bladerf_source_c.cc
@@ -142,6 +142,8 @@ int bladerf_source_c::work( int noutput_items,
int16_t *current;
const float scaling = 1.0f / 2048.0f;
gr_complex *out = static_cast<gr_complex *>(output_items[0]);
+ struct bladerf_metadata meta;
+ struct bladerf_metadata *meta_ptr = NULL;
if (noutput_items > _conv_buf_size) {
void *tmp;
@@ -156,9 +158,15 @@ int bladerf_source_c::work( int noutput_items,
_conv_buf = static_cast<int16_t*>(tmp);
}
+ if (_use_metadata) {
+ memset(&meta, 0, sizeof(meta));
+ meta.flags = BLADERF_META_FLAG_RX_NOW;
+ meta_ptr = &meta;
+ }
+
/* Grab all the samples into the temporary buffer */
ret = bladerf_sync_rx(_dev.get(), static_cast<void *>(_conv_buf),
- noutput_items, NULL, _stream_timeout_ms);
+ noutput_items, meta_ptr, _stream_timeout_ms);
if ( ret != 0 ) {
std::cerr << _pfx << "bladerf_sync_rx error: "
<< bladerf_strerror(ret) << std::endl;