summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/b100/b100_impl.hpp1
-rw-r--r--host/lib/usrp/e100/e100_impl.cpp18
-rw-r--r--host/lib/usrp/e100/e100_impl.hpp18
-rw-r--r--host/lib/usrp/e100/io_impl.cpp241
4 files changed, 162 insertions, 116 deletions
diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp
index fb440e8be..25badc967 100644
--- a/host/lib/usrp/b100/b100_impl.hpp
+++ b/host/lib/usrp/b100/b100_impl.hpp
@@ -41,6 +41,7 @@
#include <uhd/usrp/dboard_eeprom.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <uhd/transport/usb_zero_copy.hpp>
+#include <boost/weak_ptr.hpp>
static const double B100_LINK_RATE_BPS = 256e6/8; //pratical link rate (< 480 Mbps)
static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.ihx";
diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp
index 564a05a7e..deb52b2d7 100644
--- a/host/lib/usrp/e100/e100_impl.cpp
+++ b/host/lib/usrp/e100/e100_impl.cpp
@@ -271,8 +271,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){
.subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1));
fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);
_tree->create<double>(rx_dsp_path / "rate/value")
+ .set(1e6) //some default
.coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1))
- .subscribe(boost::bind(&e100_impl::update_rx_samp_rate, this, _1));
+ .subscribe(boost::bind(&e100_impl::update_rx_samp_rate, this, dspno, _1));
_tree->create<double>(rx_dsp_path / "freq/value")
.coerce(boost::bind(&rx_dsp_core_200::set_freq, _rx_dsps[dspno], _1));
_tree->create<meta_range_t>(rx_dsp_path / "freq/range")
@@ -291,8 +292,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){
_tree->access<double>(mb_path / "tick_rate")
.subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1));
_tree->create<double>(mb_path / "tx_dsps/0/rate/value")
+ .set(1e6) //some default
.coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1))
- .subscribe(boost::bind(&e100_impl::update_tx_samp_rate, this, _1));
+ .subscribe(boost::bind(&e100_impl::update_tx_samp_rate, this, 0, _1));
_tree->create<double>(mb_path / "tx_dsps/0/freq/value")
.coerce(boost::bind(&tx_dsp_core_200::set_freq, _tx_dsp, _1));
_tree->create<meta_range_t>(mb_path / "tx_dsps/0/freq/range")
@@ -376,16 +378,10 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){
////////////////////////////////////////////////////////////////////
// do some post-init tasks
////////////////////////////////////////////////////////////////////
- _tree->access<double>(mb_path / "tick_rate").update() //update and then subscribe the clock callback
- .subscribe(boost::bind(&e100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1));
+ this->update_rates();
- //and now that the tick rate is set, init the host rates to something
- BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){
- _tree->access<double>(mb_path / "rx_dsps" / name / "rate" / "value").set(1e6);
- }
- BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){
- _tree->access<double>(mb_path / "tx_dsps" / name / "rate" / "value").set(1e6);
- }
+ _tree->access<double>(mb_path / "tick_rate") //now subscribe the clock rate setter
+ .subscribe(boost::bind(&e100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1));
_tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0]));
_tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_tx_subdev_names()[0]));
diff --git a/host/lib/usrp/e100/e100_impl.hpp b/host/lib/usrp/e100/e100_impl.hpp
index 4b2ec5ee0..954d6bd93 100644
--- a/host/lib/usrp/e100/e100_impl.hpp
+++ b/host/lib/usrp/e100/e100_impl.hpp
@@ -33,11 +33,10 @@
#include <uhd/usrp/mboard_eeprom.hpp>
#include <uhd/usrp/gps_ctrl.hpp>
#include <uhd/types/sensors.hpp>
-#include <uhd/types/otw_type.hpp>
-#include <uhd/types/clock_config.hpp>
#include <uhd/types/stream_cmd.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <uhd/transport/zero_copy.hpp>
+#include <boost/weak_ptr.hpp>
#ifndef INCLUDED_E100_IMPL_HPP
#define INCLUDED_E100_IMPL_HPP
@@ -78,11 +77,9 @@ public:
~e100_impl(void);
//the io interface
- size_t send(const send_buffs_type &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double);
- size_t recv(const recv_buffs_type &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double);
+ uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args);
+ uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args);
bool recv_async_msg(uhd::async_metadata_t &, double);
- size_t get_max_send_samps_per_packet(void) const;
- size_t get_max_recv_samps_per_packet(void) const;
private:
uhd::property_tree::sptr _tree;
@@ -110,7 +107,6 @@ private:
uhd::usrp::dboard_iface::sptr _dboard_iface;
//handle io stuff
- uhd::otw_type_t _rx_otw_type, _tx_otw_type;
UHD_PIMPL_DECL(io_impl) _io_impl;
void io_init(void);
@@ -119,12 +115,16 @@ private:
return _tree;
}
+ std::vector<boost::weak_ptr<uhd::rx_streamer> > _rx_streamers;
+ std::vector<boost::weak_ptr<uhd::tx_streamer> > _tx_streamers;
+
double update_rx_codec_gain(const double); //sets A and B at once
void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &);
void set_db_eeprom(const std::string &, const uhd::usrp::dboard_eeprom_t &);
void update_tick_rate(const double rate);
- void update_rx_samp_rate(const double rate);
- void update_tx_samp_rate(const double rate);
+ void update_rx_samp_rate(const size_t, const double rate);
+ void update_tx_samp_rate(const size_t, const double rate);
+ void update_rates(void);
void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &);
void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &);
void update_clock_source(const std::string &);
diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp
index 0b81c1a86..5936ee2d7 100644
--- a/host/lib/usrp/e100/io_impl.cpp
+++ b/host/lib/usrp/e100/io_impl.cpp
@@ -35,6 +35,7 @@
#include <fcntl.h> //open, close
#include <sstream>
#include <fstream>
+#include <boost/make_shared.hpp>
using namespace uhd;
using namespace uhd::usrp;
@@ -60,10 +61,6 @@ struct e100_impl::io_impl{
//which is after the states and booty which may hold managed buffers.
recv_packet_demuxer::sptr demuxer;
- //state management for the vrt packet handler code
- sph::recv_packet_handler recv_handler;
- sph::send_packet_handler send_handler;
-
//a pirate's life is the life for me!
void recv_pirate_loop(
spi_iface::sptr //keep a sptr to iface which shares gpio147
@@ -159,16 +156,6 @@ void e100_impl::io_impl::handle_irq(void){
**********************************************************************/
void e100_impl::io_init(void){
- //setup rx otw type
- _rx_otw_type.width = 16;
- _rx_otw_type.shift = 0;
- _rx_otw_type.byteorder = uhd::otw_type_t::BO_LITTLE_ENDIAN;
-
- //setup tx otw type
- _tx_otw_type.width = 16;
- _tx_otw_type.shift = 0;
- _tx_otw_type.byteorder = uhd::otw_type_t::BO_LITTLE_ENDIAN;
-
//create new io impl
_io_impl = UHD_PIMPL_MAKE(io_impl, ());
_io_impl->demuxer = recv_packet_demuxer::make(_data_transport, _rx_dsps.size(), E100_RX_SID_BASE);
@@ -178,6 +165,10 @@ void e100_impl::io_init(void){
_fpga_ctrl->poke32(E100_REG_CLEAR_RX, 0);
_fpga_ctrl->poke32(E100_REG_CLEAR_TX, 0);
+ //allocate streamer weak ptrs containers
+ _rx_streamers.resize(_rx_dsps.size());
+ _tx_streamers.resize(1/*known to be 1 dsp*/);
+
//prepare the async msg buffer for incoming messages
_fpga_ctrl->poke32(E100_REG_SR_ERR_CTRL, 1 << 0); //clear
while ((_fpga_ctrl->peek32(E100_REG_RB_ERR_STATUS) & (1 << 2)) == 0){} //wait for idle
@@ -187,37 +178,58 @@ void e100_impl::io_init(void){
_io_impl->pirate_task = task::make(boost::bind(
&e100_impl::io_impl::recv_pirate_loop, _io_impl.get(), _aux_spi_iface
));
-
- //init some handler stuff
- _io_impl->recv_handler.set_vrt_unpacker(&vrt::if_hdr_unpack_le);
- _io_impl->recv_handler.set_converter(_rx_otw_type);
- _io_impl->send_handler.set_vrt_packer(&vrt::if_hdr_pack_le);
- _io_impl->send_handler.set_converter(_tx_otw_type);
- _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet());
}
void e100_impl::update_tick_rate(const double rate){
_io_impl->tick_rate = rate;
- boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock();
- _io_impl->recv_handler.set_tick_rate(rate);
- boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock();
- _io_impl->send_handler.set_tick_rate(rate);
+
+ //update the tick rate on all existing streamers -> thread safe
+ for (size_t i = 0; i < _rx_streamers.size(); i++){
+ boost::shared_ptr<sph::recv_packet_streamer> my_streamer =
+ boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_rx_streamers[i].lock());
+ if (my_streamer.get() == NULL) continue;
+ my_streamer->set_tick_rate(rate);
+ }
+ for (size_t i = 0; i < _tx_streamers.size(); i++){
+ boost::shared_ptr<sph::send_packet_streamer> my_streamer =
+ boost::dynamic_pointer_cast<sph::send_packet_streamer>(_tx_streamers[i].lock());
+ if (my_streamer.get() == NULL) continue;
+ my_streamer->set_tick_rate(rate);
+ }
}
-void e100_impl::update_rx_samp_rate(const double rate){
- boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock();
- _io_impl->recv_handler.set_samp_rate(rate);
- const double adj = _rx_dsps.front()->get_scaling_adjustment();
- _io_impl->recv_handler.set_scale_factor(adj/32767.);
+void e100_impl::update_rx_samp_rate(const size_t dspno, const double rate){
+ boost::shared_ptr<sph::recv_packet_streamer> my_streamer =
+ boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_rx_streamers[dspno].lock());
+ if (my_streamer.get() == NULL) return;
+
+ my_streamer->set_samp_rate(rate);
+ const double adj = _rx_dsps[dspno]->get_scaling_adjustment();
+ my_streamer->set_scale_factor(adj);
+}
+
+void e100_impl::update_tx_samp_rate(const size_t dspno, const double rate){
+ boost::shared_ptr<sph::send_packet_streamer> my_streamer =
+ boost::dynamic_pointer_cast<sph::send_packet_streamer>(_tx_streamers[dspno].lock());
+ if (my_streamer.get() == NULL) return;
+
+ my_streamer->set_samp_rate(rate);
}
-void e100_impl::update_tx_samp_rate(const double rate){
- boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock();
- _io_impl->send_handler.set_samp_rate(rate);
+void e100_impl::update_rates(void){
+ const fs_path mb_path = "/mboards/0";
+ _tree->access<double>(mb_path / "tick_rate").update();
+
+ //and now that the tick rate is set, init the host rates to something
+ BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){
+ _tree->access<double>(mb_path / "rx_dsps" / name / "rate" / "value").update();
+ }
+ BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){
+ _tree->access<double>(mb_path / "tx_dsps" / name / "rate" / "value").update();
+ }
}
void e100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){
- boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock();
fs_path root = "/mboards/0/dboards";
//sanity checking
@@ -231,22 +243,9 @@ void e100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){
_rx_dsps[i]->set_mux(conn, fe_swapped);
}
_rx_fe->set_mux(fe_swapped);
-
- //resize for the new occupancy
- _io_impl->recv_handler.resize(spec.size());
-
- //bind new callbacks for the handler
- for (size_t i = 0; i < _io_impl->recv_handler.size(); i++){
- _rx_dsps[i]->set_nsamps_per_packet(get_max_recv_samps_per_packet()); //seems to be a good place to set this
- _io_impl->recv_handler.set_xport_chan_get_buff(i, boost::bind(
- &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, i, _1
- ));
- _io_impl->recv_handler.set_overflow_handler(i, boost::bind(&rx_dsp_core_200::handle_overflow, _rx_dsps[i]));
- }
}
void e100_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){
- boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock();
fs_path root = "/mboards/0/dboards";
//sanity checking
@@ -255,73 +254,123 @@ void e100_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){
//set the mux for this spec
const std::string conn = _tree->access<std::string>(root / spec[0].db_name / "tx_frontends" / spec[0].sd_name / "connection").get();
_tx_fe->set_mux(conn);
+}
- //resize for the new occupancy
- _io_impl->send_handler.resize(spec.size());
-
- //bind new callbacks for the handler
- for (size_t i = 0; i < _io_impl->send_handler.size(); i++){
- _io_impl->send_handler.set_xport_chan_get_buff(i, boost::bind(
- &zero_copy_if::get_send_buff, _data_transport, _1
- ));
- }
+/***********************************************************************
+ * Async Recv
+ **********************************************************************/
+bool e100_impl::recv_async_msg(
+ async_metadata_t &async_metadata, double timeout
+){
+ boost::this_thread::disable_interruption di; //disable because the wait can throw
+ return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout);
}
/***********************************************************************
- * Data Send
+ * Receive streamer
**********************************************************************/
-size_t e100_impl::get_max_send_samps_per_packet(void) const{
+rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){
+ stream_args_t args = args_;
+
+ //setup defaults for unspecified values
+ args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;
+ args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
+
+ //calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
;
- size_t bpp = _data_transport->get_send_frame_size() - hdr_size;
- return bpp/_tx_otw_type.get_sample_size();
-}
+ const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size;
+ const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format);
+
+ //make the new streamer given the samples per packet
+ boost::shared_ptr<sph::recv_packet_streamer> my_streamer = boost::make_shared<sph::recv_packet_streamer>(spp);
+
+ //init some streamer stuff
+ my_streamer->resize(args.channels.size());
+ my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_le);
+
+ //set the converter
+ uhd::convert::id_type id;
+ id.input_markup = args.otw_format + "_item32_le";
+ id.num_inputs = 1;
+ id.output_markup = args.cpu_format;
+ id.num_outputs = 1;
+ id.args = args.args;
+ my_streamer->set_converter(id);
+
+ //bind callbacks for the handler
+ for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){
+ const size_t dsp = args.channels[chan_i];
+ _rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this
+ _rx_dsps[dsp]->set_format(args.otw_format, 0x400);
+ my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
+ &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1
+ ));
+ my_streamer->set_overflow_handler(chan_i, boost::bind(
+ &rx_dsp_core_200::handle_overflow, _rx_dsps[dsp]
+ ));
+ _rx_streamers[dsp] = my_streamer; //store weak pointer
+ }
-size_t e100_impl::send(
- const send_buffs_type &buffs, size_t nsamps_per_buff,
- const tx_metadata_t &metadata, const io_type_t &io_type,
- send_mode_t send_mode, double timeout
-){
- return _io_impl->send_handler.send(
- buffs, nsamps_per_buff,
- metadata, io_type,
- send_mode, timeout
- );
+ //sets all tick and samp rates on this streamer
+ this->update_rates();
+
+ return my_streamer;
}
/***********************************************************************
- * Data Recv
+ * Transmit streamer
**********************************************************************/
-size_t e100_impl::get_max_recv_samps_per_packet(void) const{
+tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){
+ stream_args_t args = args_;
+
+ //setup defaults for unspecified values
+ args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;
+ args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
+
+ if (args.otw_format != "sc16"){
+ throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format);
+ }
+
+ //calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
- + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
;
- size_t bpp = _data_transport->get_recv_frame_size() - hdr_size;
- return bpp/_rx_otw_type.get_sample_size();
-}
+ static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size;
+ const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format);
+
+ //make the new streamer given the samples per packet
+ boost::shared_ptr<sph::send_packet_streamer> my_streamer = boost::make_shared<sph::send_packet_streamer>(spp);
+
+ //init some streamer stuff
+ my_streamer->resize(args.channels.size());
+ my_streamer->set_vrt_packer(&vrt::if_hdr_pack_le);
+
+ //set the converter
+ uhd::convert::id_type id;
+ id.input_markup = args.cpu_format;
+ id.num_inputs = 1;
+ id.output_markup = args.otw_format + "_item32_le";
+ id.num_outputs = 1;
+ id.args = args.args;
+ my_streamer->set_converter(id);
+
+ //bind callbacks for the handler
+ for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){
+ const size_t dsp = args.channels[chan_i];
+ UHD_ASSERT_THROW(dsp == 0); //always 0
+ my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
+ &zero_copy_if::get_send_buff, _data_transport, _1
+ ));
+ _tx_streamers[dsp] = my_streamer; //store weak pointer
+ }
-size_t e100_impl::recv(
- const recv_buffs_type &buffs, size_t nsamps_per_buff,
- rx_metadata_t &metadata, const io_type_t &io_type,
- recv_mode_t recv_mode, double timeout
-){
- return _io_impl->recv_handler.recv(
- buffs, nsamps_per_buff,
- metadata, io_type,
- recv_mode, timeout
- );
-}
+ //sets all tick and samp rates on this streamer
+ this->update_rates();
-/***********************************************************************
- * Async Recv
- **********************************************************************/
-bool e100_impl::recv_async_msg(
- async_metadata_t &async_metadata, double timeout
-){
- boost::this_thread::disable_interruption di; //disable because the wait can throw
- return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout);
+ return my_streamer;
}