aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp2
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp2')
-rw-r--r--host/lib/usrp2/io_impl.cpp77
-rw-r--r--host/lib/usrp2/usrp2_impl.cpp276
-rw-r--r--host/lib/usrp2/usrp2_impl.hpp19
3 files changed, 231 insertions, 141 deletions
diff --git a/host/lib/usrp2/io_impl.cpp b/host/lib/usrp2/io_impl.cpp
index 4232b0151..fde02577c 100644
--- a/host/lib/usrp2/io_impl.cpp
+++ b/host/lib/usrp2/io_impl.cpp
@@ -32,7 +32,6 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/barrier.hpp>
-#include <numeric>
#include <iostream>
using namespace uhd;
@@ -135,8 +134,7 @@ private:
**********************************************************************/
struct usrp2_impl::io_impl{
- io_impl(const size_t mboards):
- rx_chan_occ(mboards), tx_chan_occ(mboards),
+ io_impl(void):
async_msg_fifo(100/*messages deep*/)
{
/* NOP */
@@ -162,9 +160,6 @@ struct usrp2_impl::io_impl{
return buff;
}
- //subdev spec mapping information
- std::vector<size_t> rx_chan_occ, tx_chan_occ;
-
//tx dsp: xports and flow control monitors
std::vector<zero_copy_if::sptr> tx_xports;
std::vector<flow_control_monitor::sptr> fc_mons;
@@ -257,25 +252,26 @@ void usrp2_impl::io_init(void){
_tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
//create new io impl
- _io_impl = UHD_PIMPL_MAKE(io_impl, (_mboard_stuff.size()));
+ _io_impl = UHD_PIMPL_MAKE(io_impl, ());
//init first so we dont have an access race
- for (size_t i = 0; i < _mboard_stuff.size(); i++){
+ BOOST_FOREACH(const std::string &mb, _mbc.keys()){
//init the tx xport and flow control monitor
- _io_impl->tx_xports.push_back(_mboard_stuff[i].dsp_xports.at(0));
+ _io_impl->tx_xports.push_back(_mbc[mb].dsp_xports.at(0));
_io_impl->fc_mons.push_back(flow_control_monitor::sptr(new flow_control_monitor(
- USRP2_SRAM_BYTES/_mboard_stuff[i].dsp_xports.at(0)->get_send_frame_size()
+ USRP2_SRAM_BYTES/_mbc[mb].dsp_xports.at(0)->get_send_frame_size()
)));
}
//create a new pirate thread for each zc if (yarr!!)
- boost::barrier spawn_barrier(_mboard_stuff.size()+1);
- for (size_t i = 0; i < _mboard_stuff.size(); i++){
+ boost::barrier spawn_barrier(_mbc.size()+1);
+ size_t index = 0;
+ BOOST_FOREACH(const std::string &mb, _mbc.keys()){
//spawn a new pirate to plunder the recv booty
_io_impl->recv_pirate_crew.create_thread(boost::bind(
&usrp2_impl::io_impl::recv_pirate_loop,
_io_impl.get(), boost::ref(spawn_barrier),
- _mboard_stuff[i].err_xports.at(0), i
+ _mbc[mb].err_xports.at(0), index++
));
}
spawn_barrier.wait();
@@ -306,34 +302,48 @@ void usrp2_impl::update_tx_samp_rate(const double rate){
_io_impl->send_handler.set_samp_rate(rate);
}
-void usrp2_impl::update_rx_subdev_spec(const size_t which_mb, const subdev_spec_t &spec_){
+void usrp2_impl::update_rx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec_){
boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock();
+ property_tree::path_type root = "/mboards/" + which_mb + "/dboards";
- //sanity checking TODO
+ //sanity checking
subdev_spec_t spec(spec_);
+ if (spec.size() == 0){
+ //determine the first subdev spec that exists
+ const std::string db_name = _tree->list(root).at(0);
+ const std::string sd_name = _tree->list(root / db_name / "rx_frontends").at(0);
+ spec.push_back(subdev_spec_pair_t(db_name, sd_name));
+ }
+ if (spec.size() > _mbc[which_mb].rx_dsps.size()) throw uhd::value_error("rx subdev spec too long");
- //TODO setup mux for this spec
+ //setup mux for this spec
+ for (size_t i = 0; i < spec.size(); i++){
+ //ASSUME that we dont swap the rx fe mux...
+ const std::string conn = _tree->access<std::string>(root / spec[i].db_name / "rx_frontends" / spec[i].sd_name / "connection").get();
+ _mbc[which_mb].rx_dsps[i]->set_mux(conn);
+ }
//compute the new occupancy and resize
- _io_impl->rx_chan_occ[which_mb] = spec.size();
- const size_t nchan = std::accumulate(_io_impl->rx_chan_occ.begin(), _io_impl->rx_chan_occ.end(), 0);
+ _mbc[which_mb].rx_chan_occ = spec.size();
+ size_t nchan = 0;
+ BOOST_FOREACH(const std::string &mb, _mbc.keys()) nchan += _mbc[mb].rx_chan_occ;
_io_impl->recv_handler.resize(nchan);
//bind new callbacks for the handler
size_t chan = 0;
- for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){
- for (size_t dsp = 0; dsp < _io_impl->rx_chan_occ[mb]; dsp++){
- _mboard_stuff[mb].rx_dsps[dsp]->set_nsamps_per_packet(get_max_recv_samps_per_packet()); //seems to be a good place to set this
+ BOOST_FOREACH(const std::string &mb, _mbc.keys()){
+ for (size_t dsp = 0; dsp < _mbc[mb].rx_chan_occ; dsp++){
+ _mbc[mb].rx_dsps[dsp]->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(chan++, boost::bind(
- &zero_copy_if::get_recv_buff, _mboard_stuff[mb].dsp_xports[dsp], _1
+ &zero_copy_if::get_recv_buff, _mbc[mb].dsp_xports[dsp], _1
));
}
}
}
-void usrp2_impl::update_tx_subdev_spec(const size_t which_mb, const subdev_spec_t &spec_){
+void usrp2_impl::update_tx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec_){
boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock();
- property_tree::path_type root = str(boost::format("/mboards/%u/dboards") % which_mb);
+ property_tree::path_type root = "/mboards/" + which_mb + "/dboards";
//sanity checking
subdev_spec_t spec(spec_);
@@ -347,19 +357,20 @@ void usrp2_impl::update_tx_subdev_spec(const size_t which_mb, const subdev_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();
- _mboard_stuff[which_mb].tx_fe->set_mux(conn);
+ _mbc[which_mb].tx_fe->set_mux(conn);
//compute the new occupancy and resize
- _io_impl->tx_chan_occ[which_mb] = spec.size();
- const size_t nchan = std::accumulate(_io_impl->tx_chan_occ.begin(), _io_impl->tx_chan_occ.end(), 0);
+ _mbc[which_mb].tx_chan_occ = spec.size();
+ size_t nchan = 0;
+ BOOST_FOREACH(const std::string &mb, _mbc.keys()) nchan += _mbc[mb].tx_chan_occ;
_io_impl->send_handler.resize(nchan);
//bind new callbacks for the handler
- size_t chan = 0;
- for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){
- for (size_t dsp = 0; dsp < _io_impl->tx_chan_occ[mb]; dsp++){
+ size_t chan = 0, i = 0;
+ BOOST_FOREACH(const std::string &mb, _mbc.keys()){
+ for (size_t dsp = 0; dsp < _mbc[mb].tx_chan_occ; dsp++){
_io_impl->send_handler.set_xport_chan_get_buff(chan++, boost::bind(
- &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), mb, _1
+ &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), i++, _1
));
}
}
@@ -384,7 +395,7 @@ size_t usrp2_impl::get_max_send_samps_per_packet(void) const{
+ vrt_send_header_offset_words32*sizeof(boost::uint32_t)
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
;
- const size_t bpp = _mboard_stuff[0].dsp_xports[0]->get_send_frame_size() - hdr_size;
+ const size_t bpp = _mbc[_mbc.keys().front()].dsp_xports[0]->get_send_frame_size() - hdr_size;
return bpp/_tx_otw_type.get_sample_size();
}
@@ -409,7 +420,7 @@ size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{
+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
;
- const size_t bpp = _mboard_stuff[0].dsp_xports[0]->get_recv_frame_size() - hdr_size;
+ const size_t bpp = _mbc[_mbc.keys().front()].dsp_xports[0]->get_recv_frame_size() - hdr_size;
return bpp/_rx_otw_type.get_sample_size();
}
diff --git a/host/lib/usrp2/usrp2_impl.cpp b/host/lib/usrp2/usrp2_impl.cpp
index 1c85aae9c..7dc9ac812 100644
--- a/host/lib/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp2/usrp2_impl.cpp
@@ -31,6 +31,7 @@
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
+#include <boost/assign/list_of.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/asio.hpp> //used for htonl and ntohl
@@ -293,54 +294,54 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
////////////////////////////////////////////////////////////////////
_tree = property_tree::make();
- _mboard_stuff.resize(device_args.size());
- for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){
-
- const std::string addr = device_args[mb]["addr"];
- property_tree::path_type mb_path = str(boost::format("/mboards/%u") % mb);
+ for (size_t mbi = 0; mbi < device_args.size(); mbi++){
+ const device_addr_t device_args_i = device_args[mbi];
+ const std::string mb = boost::lexical_cast<std::string>(mbi);
+ const std::string addr = device_args_i["addr"];
+ property_tree::path_type mb_path = "/mboards/" + mb;
////////////////////////////////////////////////////////////////
// construct transports for dsp and async errors
////////////////////////////////////////////////////////////////
UHD_LOG << "Making transport for DSP0..." << std::endl;
- _mboard_stuff[mb].dsp_xports.push_back(udp_zero_copy::make(
- addr, BOOST_STRINGIZE(USRP2_UDP_DSP0_PORT), device_args[mb]
+ _mbc[mb].dsp_xports.push_back(udp_zero_copy::make(
+ addr, BOOST_STRINGIZE(USRP2_UDP_DSP0_PORT), device_args_i
));
- init_xport(_mboard_stuff[mb].dsp_xports.back());
+ init_xport(_mbc[mb].dsp_xports.back());
UHD_LOG << "Making transport for DSP1..." << std::endl;
- _mboard_stuff[mb].dsp_xports.push_back(udp_zero_copy::make(
- addr, BOOST_STRINGIZE(USRP2_UDP_DSP1_PORT), device_args[mb]
+ _mbc[mb].dsp_xports.push_back(udp_zero_copy::make(
+ addr, BOOST_STRINGIZE(USRP2_UDP_DSP1_PORT), device_args_i
));
- init_xport(_mboard_stuff[mb].dsp_xports.back());
+ init_xport(_mbc[mb].dsp_xports.back());
UHD_LOG << "Making transport for ERR0..." << std::endl;
- _mboard_stuff[mb].err_xports.push_back(udp_zero_copy::make(
+ _mbc[mb].err_xports.push_back(udp_zero_copy::make(
addr, BOOST_STRINGIZE(USRP2_UDP_ERR0_PORT), device_addr_t()
));
- init_xport(_mboard_stuff[mb].err_xports.back());
+ init_xport(_mbc[mb].err_xports.back());
////////////////////////////////////////////////////////////////
// create the iface that controls i2c, spi, uart, and wb
////////////////////////////////////////////////////////////////
- _mboard_stuff[mb].iface = usrp2_iface::make(udp_simple::make_connected(
+ _mbc[mb].iface = usrp2_iface::make(udp_simple::make_connected(
addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)
));
- _tree->create<std::string>(mb_path / "name").set(_mboard_stuff[mb].iface->get_cname());
+ _tree->create<std::string>(mb_path / "name").set(_mbc[mb].iface->get_cname());
////////////////////////////////////////////////////////////////
// setup the mboard eeprom
////////////////////////////////////////////////////////////////
_tree->create<mboard_eeprom_t>(mb_path / "eeprom")
- .set(_mboard_stuff[mb].iface->mb_eeprom)
+ .set(_mbc[mb].iface->mb_eeprom)
.subscribe(boost::bind(&usrp2_impl::set_mb_eeprom, this, mb, _1));
////////////////////////////////////////////////////////////////
// create clock control objects
////////////////////////////////////////////////////////////////
- _mboard_stuff[mb].clock = usrp2_clock_ctrl::make(_mboard_stuff[mb].iface);
+ _mbc[mb].clock = usrp2_clock_ctrl::make(_mbc[mb].iface);
_tree->create<double>(mb_path / "tick_rate")
- .publish(boost::bind(&usrp2_clock_ctrl::get_master_clock_rate, _mboard_stuff[mb].clock))
+ .publish(boost::bind(&usrp2_clock_ctrl::get_master_clock_rate, _mbc[mb].clock))
.subscribe(boost::bind(&usrp2_impl::update_tick_rate, this, _1));
////////////////////////////////////////////////////////////////
@@ -348,8 +349,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
////////////////////////////////////////////////////////////////
property_tree::path_type rx_codec_path = mb_path / "rx_codecs/A";
property_tree::path_type tx_codec_path = mb_path / "tx_codecs/A";
- _mboard_stuff[mb].codec = usrp2_codec_ctrl::make(_mboard_stuff[mb].iface);
- switch(_mboard_stuff[mb].iface->get_rev()){
+ _mbc[mb].codec = usrp2_codec_ctrl::make(_mbc[mb].iface);
+ switch(_mbc[mb].iface->get_rev()){
case usrp2_iface::USRP_N200:
case usrp2_iface::USRP_N210:
case usrp2_iface::USRP_N200_R4:
@@ -357,10 +358,10 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
_tree->create<std::string>(rx_codec_path / "name").set("ads62p44");
_tree->create<meta_range_t>(rx_codec_path / "gains/digital/range").set(meta_range_t(0, 6.0, 0.5));
_tree->create<double>(rx_codec_path / "gains/digital/value")
- .subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_gain, _mboard_stuff[mb].codec, _1));
+ .subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_gain, _mbc[mb].codec, _1));
_tree->create<meta_range_t>(rx_codec_path / "gains/fine/range").set(meta_range_t(0, 0.5, 0.05));
_tree->create<double>(rx_codec_path / "gains/fine/value")
- .subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_fine_gain, _mboard_stuff[mb].codec, _1));
+ .subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_fine_gain, _mbc[mb].codec, _1));
}break;
case usrp2_iface::USRP2_REV3:
@@ -377,14 +378,14 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
////////////////////////////////////////////////////////////////
// create gpsdo control objects
////////////////////////////////////////////////////////////////
- if (_mboard_stuff[mb].iface->mb_eeprom["gpsdo"] == "internal"){
- _mboard_stuff[mb].gps = gps_ctrl::make(
- _mboard_stuff[mb].iface->get_gps_write_fn(),
- _mboard_stuff[mb].iface->get_gps_read_fn()
+ if (_mbc[mb].iface->mb_eeprom["gpsdo"] == "internal"){
+ _mbc[mb].gps = gps_ctrl::make(
+ _mbc[mb].iface->get_gps_write_fn(),
+ _mbc[mb].iface->get_gps_read_fn()
);
- BOOST_FOREACH(const std::string &name, _mboard_stuff[mb].gps->get_sensors()){
+ BOOST_FOREACH(const std::string &name, _mbc[mb].gps->get_sensors()){
_tree->create<sensor_value_t>(mb_path / "sensors" / name)
- .publish(boost::bind(&gps_ctrl::get_sensor, _mboard_stuff[mb].gps, name));
+ .publish(boost::bind(&gps_ctrl::get_sensor, _mbc[mb].gps, name));
}
}
@@ -396,27 +397,14 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
_tree->create<sensor_value_t>(mb_path / "sensors/ref_locked")
.publish(boost::bind(&usrp2_impl::get_ref_locked, this, mb));
-
-
- //TODO //initialize VITA time to GPS time
-
- //TODO clock source, time source
- //and if gps is present, set to external automatically
-
-
-
-
-
-
-
////////////////////////////////////////////////////////////////
// create frontend control objects
////////////////////////////////////////////////////////////////
- _mboard_stuff[mb].rx_fe = rx_frontend_core_200::make(
- _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_RX_FRONT)
+ _mbc[mb].rx_fe = rx_frontend_core_200::make(
+ _mbc[mb].iface, U2_REG_SR_ADDR(SR_RX_FRONT)
);
- _mboard_stuff[mb].tx_fe = tx_frontend_core_200::make(
- _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_TX_FRONT)
+ _mbc[mb].tx_fe = tx_frontend_core_200::make(
+ _mbc[mb].iface, U2_REG_SR_ADDR(SR_TX_FRONT)
);
//TODO lots of properties to expose here for frontends
_tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec")
@@ -427,48 +415,48 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
////////////////////////////////////////////////////////////////
// create rx dsp control objects
////////////////////////////////////////////////////////////////
- _mboard_stuff[mb].rx_dsps.push_back(rx_dsp_core_200::make(
- _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_RX_DSP0), U2_REG_SR_ADDR(SR_RX_CTRL0), USRP2_RX_SID_BASE + 0, true
+ _mbc[mb].rx_dsps.push_back(rx_dsp_core_200::make(
+ _mbc[mb].iface, U2_REG_SR_ADDR(SR_RX_DSP0), U2_REG_SR_ADDR(SR_RX_CTRL0), USRP2_RX_SID_BASE + 0, true
));
- _mboard_stuff[mb].rx_dsps.push_back(rx_dsp_core_200::make(
- _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_RX_DSP1), U2_REG_SR_ADDR(SR_RX_CTRL1), USRP2_RX_SID_BASE + 1, true
+ _mbc[mb].rx_dsps.push_back(rx_dsp_core_200::make(
+ _mbc[mb].iface, U2_REG_SR_ADDR(SR_RX_DSP1), U2_REG_SR_ADDR(SR_RX_CTRL1), USRP2_RX_SID_BASE + 1, true
));
- for (size_t dspno = 0; dspno < _mboard_stuff[mb].rx_dsps.size(); dspno++){
+ for (size_t dspno = 0; dspno < _mbc[mb].rx_dsps.size(); dspno++){
_tree->access<double>(mb_path / "tick_rate")
- .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _mboard_stuff[mb].rx_dsps[dspno], _1));
+ .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _mbc[mb].rx_dsps[dspno], _1));
//This is a hack/fix for the lingering packet problem.
//The dsp core starts streaming briefly... now we flush
- _mboard_stuff[mb].dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for lingering
- _mboard_stuff[mb].dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected
+ _mbc[mb].dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for lingering
+ _mbc[mb].dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected
property_tree::path_type rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);
_tree->create<double>(rx_dsp_path / "rate/value")
- .subscribe_master(boost::bind(&rx_dsp_core_200::set_host_rate, _mboard_stuff[mb].rx_dsps[dspno], _1))
+ .subscribe_master(boost::bind(&rx_dsp_core_200::set_host_rate, _mbc[mb].rx_dsps[dspno], _1))
.subscribe(boost::bind(&usrp2_impl::update_rx_samp_rate, this, _1));
_tree->create<double>(rx_dsp_path / "freq/value")
- .subscribe_master(boost::bind(&rx_dsp_core_200::set_freq, _mboard_stuff[mb].rx_dsps[dspno], _1));
+ .subscribe_master(boost::bind(&rx_dsp_core_200::set_freq, _mbc[mb].rx_dsps[dspno], _1));
_tree->create<stream_cmd_t>(rx_dsp_path / "stream_cmd")
- .subscribe(boost::bind(&rx_dsp_core_200::issue_stream_command, _mboard_stuff[mb].rx_dsps[dspno], _1));
+ .subscribe(boost::bind(&rx_dsp_core_200::issue_stream_command, _mbc[mb].rx_dsps[dspno], _1));
}
////////////////////////////////////////////////////////////////
// create tx dsp control objects
////////////////////////////////////////////////////////////////
- _mboard_stuff[mb].tx_dsp = tx_dsp_core_200::make(
- _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_TX_DSP), U2_REG_SR_ADDR(SR_TX_CTRL), USRP2_TX_ASYNC_SID
+ _mbc[mb].tx_dsp = tx_dsp_core_200::make(
+ _mbc[mb].iface, U2_REG_SR_ADDR(SR_TX_DSP), U2_REG_SR_ADDR(SR_TX_CTRL), USRP2_TX_ASYNC_SID
);
_tree->access<double>(mb_path / "tick_rate")
- .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mboard_stuff[mb].tx_dsp, _1));
+ .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1));
_tree->create<double>(mb_path / "tx_dsps/0/rate/value")
- .subscribe_master(boost::bind(&tx_dsp_core_200::set_host_rate, _mboard_stuff[mb].tx_dsp, _1))
+ .subscribe_master(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1))
.subscribe(boost::bind(&usrp2_impl::update_tx_samp_rate, this, _1));
_tree->create<double>(mb_path / "tx_dsps/0/freq/value")
- .subscribe_master(boost::bind(&tx_dsp_core_200::set_freq, _mboard_stuff[mb].tx_dsp, _1));
- //TODO combine w/ codec shift
+ .subscribe_master(boost::bind(&usrp2_impl::set_tx_dsp_freq, this, mb, _1));
+
//setup dsp flow control
- const double ups_per_sec = device_args[mb].cast<double>("ups_per_sec", 20);
- const size_t send_frame_size = _mboard_stuff[mb].dsp_xports.front()->get_send_frame_size();
- const double ups_per_fifo = device_args[mb].cast<double>("ups_per_fifo", 8.0);
- _mboard_stuff[mb].tx_dsp->set_updates(
+ const double ups_per_sec = device_args_i.cast<double>("ups_per_sec", 20);
+ const size_t send_frame_size = _mbc[mb].dsp_xports.front()->get_send_frame_size();
+ const double ups_per_fifo = device_args_i.cast<double>("ups_per_fifo", 8.0);
+ _mbc[mb].tx_dsp->set_updates(
(ups_per_sec > 0.0)? size_t(100e6/*approx tick rate*//ups_per_sec) : 0,
(ups_per_fifo > 0.0)? size_t(USRP2_SRAM_BYTES/ups_per_fifo/send_frame_size) : 0
);
@@ -481,17 +469,27 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
time64_rb_bases.rb_ticks_imm = U2_REG_TIME64_TICKS_RB_IMM;
time64_rb_bases.rb_secs_pps = U2_REG_TIME64_SECS_RB_PPS;
time64_rb_bases.rb_ticks_pps = U2_REG_TIME64_TICKS_RB_PPS;
- _mboard_stuff[mb].time64 = time64_core_200::make(
- _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_TIME64), time64_rb_bases, mimo_clock_sync_delay_cycles
+ _mbc[mb].time64 = time64_core_200::make(
+ _mbc[mb].iface, U2_REG_SR_ADDR(SR_TIME64), time64_rb_bases, mimo_clock_sync_delay_cycles
);
_tree->access<double>(mb_path / "tick_rate")
- .subscribe(boost::bind(&time64_core_200::set_tick_rate, _mboard_stuff[mb].time64, _1));
+ .subscribe(boost::bind(&time64_core_200::set_tick_rate, _mbc[mb].time64, _1));
_tree->create<time_spec_t>(mb_path / "time/now")
- .publish(boost::bind(&time64_core_200::get_time_now, _mboard_stuff[mb].time64))
- .subscribe(boost::bind(&time64_core_200::set_time_now, _mboard_stuff[mb].time64, _1));
+ .publish(boost::bind(&time64_core_200::get_time_now, _mbc[mb].time64))
+ .subscribe(boost::bind(&time64_core_200::set_time_now, _mbc[mb].time64, _1));
_tree->create<time_spec_t>(mb_path / "time/pps")
- .publish(boost::bind(&time64_core_200::get_time_last_pps, _mboard_stuff[mb].time64))
- .subscribe(boost::bind(&time64_core_200::set_time_next_pps, _mboard_stuff[mb].time64, _1));
+ .publish(boost::bind(&time64_core_200::get_time_last_pps, _mbc[mb].time64))
+ .subscribe(boost::bind(&time64_core_200::set_time_next_pps, _mbc[mb].time64, _1));
+ //setup time source props
+ _tree->create<std::string>(mb_path / "time_source/value")
+ .subscribe(boost::bind(&time64_core_200::set_time_source, _mbc[mb].time64, _1));
+ _tree->create<std::vector<std::string> >(mb_path / "time_source/options")
+ .publish(boost::bind(&time64_core_200::get_time_sources, _mbc[mb].time64));
+ //setup reference source props
+ _tree->create<std::string>(mb_path / "ref_source/value")
+ .subscribe(boost::bind(&usrp2_impl::update_ref_source, this, mb, _1));
+ static const std::vector<std::string> ref_sources = boost::assign::list_of("internal")("sma")("mimo");
+ _tree->create<std::vector<std::string> >(mb_path / "ref_source/options").set(ref_sources);
////////////////////////////////////////////////////////////////
// create dboard control objects
@@ -499,9 +497,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
//read the dboard eeprom to extract the dboard ids
dboard_eeprom_t rx_db_eeprom, tx_db_eeprom, gdb_eeprom;
- rx_db_eeprom.load(*_mboard_stuff[mb].iface, USRP2_I2C_ADDR_RX_DB);
- tx_db_eeprom.load(*_mboard_stuff[mb].iface, USRP2_I2C_ADDR_TX_DB);
- gdb_eeprom.load(*_mboard_stuff[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5);
+ rx_db_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_RX_DB);
+ tx_db_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB);
+ gdb_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5);
//create the properties and register subscribers
_tree->create<dboard_eeprom_t>(mb_path / "dboards/A/rx_eeprom")
@@ -512,23 +510,23 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
.subscribe(boost::bind(&usrp2_impl::set_db_eeprom, this, mb, "gdb", _1));
//create a new dboard interface and manager
- _mboard_stuff[mb].dboard_iface = make_usrp2_dboard_iface(_mboard_stuff[mb].iface, _mboard_stuff[mb].clock);
- _tree->create<dboard_iface::sptr>(mb_path / "dboards/A/iface").set(_mboard_stuff[mb].dboard_iface);
- _mboard_stuff[mb].dboard_manager = dboard_manager::make(
+ _mbc[mb].dboard_iface = make_usrp2_dboard_iface(_mbc[mb].iface, _mbc[mb].clock);
+ _tree->create<dboard_iface::sptr>(mb_path / "dboards/A/iface").set(_mbc[mb].dboard_iface);
+ _mbc[mb].dboard_manager = dboard_manager::make(
rx_db_eeprom.id,
((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id,
- _mboard_stuff[mb].dboard_iface
+ _mbc[mb].dboard_iface
);
- BOOST_FOREACH(const std::string &name, _mboard_stuff[mb].dboard_manager->get_rx_subdev_names()){
+ BOOST_FOREACH(const std::string &name, _mbc[mb].dboard_manager->get_rx_subdev_names()){
dboard_manager::populate_prop_tree_from_subdev(
_tree, mb_path / "dboards/A/rx_frontends" / name,
- _mboard_stuff[mb].dboard_manager->get_rx_subdev(name)
+ _mbc[mb].dboard_manager->get_rx_subdev(name)
);
}
- BOOST_FOREACH(const std::string &name, _mboard_stuff[mb].dboard_manager->get_tx_subdev_names()){
+ BOOST_FOREACH(const std::string &name, _mbc[mb].dboard_manager->get_tx_subdev_names()){
dboard_manager::populate_prop_tree_from_subdev(
_tree, mb_path / "dboards/A/tx_frontends" / name,
- _mboard_stuff[mb].dboard_manager->get_tx_subdev(name)
+ _mbc[mb].dboard_manager->get_tx_subdev(name)
);
}
}
@@ -537,36 +535,114 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
this->io_init();
//do some post-init tasks
- for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){
- _tree->access<double>(str(boost::format("/mboards/%u/tick_rate") % mb)).update();
- _tree->access<subdev_spec_t>(str(boost::format("/mboards/%u/rx_subdev_spec") % mb)).set(subdev_spec_t());
- _tree->access<subdev_spec_t>(str(boost::format("/mboards/%u/tx_subdev_spec") % mb)).set(subdev_spec_t());
+ BOOST_FOREACH(const std::string &mb, _mbc.keys()){
+ property_tree::path_type root = "/mboards/" + mb;
+ _tree->access<double>(root / "tick_rate").update();
+ _tree->access<subdev_spec_t>(root / "rx_subdev_spec").set(subdev_spec_t());
+ _tree->access<subdev_spec_t>(root / "tx_subdev_spec").set(subdev_spec_t());
+ _tree->access<std::string>(root / "ref_source/value").set("internal");
+ _tree->access<std::string>(root / "time_source/value").set("none");
+
+ //GPS installed: use external ref, time, and init time spec
+ if (_mbc[mb].gps.get() != NULL){
+ _tree->access<std::string>(root / "time_source/value").set("sma");
+ _tree->access<std::string>(root / "ref_source/value").set("sma");
+ _mbc[mb].time64->set_time_next_pps(time_spec_t(time_t(_mbc[mb].gps->get_sensor("gps_time").to_int()+1)));
+ }
}
}
usrp2_impl::~usrp2_impl(void){UHD_SAFE_CALL(
- for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){
- _mboard_stuff[mb].tx_dsp->set_updates(0, 0);
+ BOOST_FOREACH(const std::string &mb, _mbc.keys()){
+ _mbc[mb].tx_dsp->set_updates(0, 0);
}
)}
-void usrp2_impl::set_mb_eeprom(const size_t which_mb, const uhd::usrp::mboard_eeprom_t &mb_eeprom){
- mb_eeprom.commit(*(_mboard_stuff[which_mb].iface), mboard_eeprom_t::MAP_N100);
+void usrp2_impl::set_mb_eeprom(const std::string &mb, const uhd::usrp::mboard_eeprom_t &mb_eeprom){
+ mb_eeprom.commit(*(_mbc[mb].iface), mboard_eeprom_t::MAP_N100);
}
-void usrp2_impl::set_db_eeprom(const size_t which_mb, const std::string &type, const uhd::usrp::dboard_eeprom_t &db_eeprom){
- if (type == "rx") db_eeprom.store(*_mboard_stuff[which_mb].iface, USRP2_I2C_ADDR_RX_DB);
- if (type == "tx") db_eeprom.store(*_mboard_stuff[which_mb].iface, USRP2_I2C_ADDR_TX_DB);
- if (type == "gdb") db_eeprom.store(*_mboard_stuff[which_mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5);
+void usrp2_impl::set_db_eeprom(const std::string &mb, const std::string &type, const uhd::usrp::dboard_eeprom_t &db_eeprom){
+ if (type == "rx") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_RX_DB);
+ if (type == "tx") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB);
+ if (type == "gdb") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5);
}
-sensor_value_t usrp2_impl::get_mimo_locked(const size_t which_mb){
- const bool lock = (_mboard_stuff[which_mb].iface->peek32(U2_REG_IRQ_RB) & (1<<10)) != 0;
+sensor_value_t usrp2_impl::get_mimo_locked(const std::string &mb){
+ const bool lock = (_mbc[mb].iface->peek32(U2_REG_IRQ_RB) & (1<<10)) != 0;
return sensor_value_t("MIMO", lock, "locked", "unlocked");
}
-sensor_value_t usrp2_impl::get_ref_locked(const size_t which_mb){
- const bool lock = (_mboard_stuff[which_mb].iface->peek32(U2_REG_IRQ_RB) & (1<<11)) != 0;
+sensor_value_t usrp2_impl::get_ref_locked(const std::string &mb){
+ const bool lock = (_mbc[mb].iface->peek32(U2_REG_IRQ_RB) & (1<<11)) != 0;
return sensor_value_t("Ref", lock, "locked", "unlocked");
}
+
+#include <boost/math/special_functions/round.hpp>
+#include <boost/math/special_functions/sign.hpp>
+
+double usrp2_impl::set_tx_dsp_freq(const std::string &mb, const double freq_){
+ double new_freq = freq_;
+ const double tick_rate = _tree->access<double>("/mboards/"+mb+"/tick_rate").get();
+
+ //calculate the DAC shift (multiples of rate)
+ const int sign = boost::math::sign(new_freq);
+ const int zone = std::min(boost::math::iround(new_freq/tick_rate), 2);
+ const double dac_shift = sign*zone*tick_rate;
+ new_freq -= dac_shift; //update FPGA DSP target freq
+
+ //set the DAC shift (modulation mode)
+ if (zone == 0) _mbc[mb].codec->set_tx_mod_mode(0); //no shift
+ else _mbc[mb].codec->set_tx_mod_mode(sign*4/zone); //DAC interp = 4
+
+ return _mbc[mb].tx_dsp->set_freq(new_freq) + dac_shift; //actual freq
+}
+
+void usrp2_impl::update_ref_source(const std::string &mb, const std::string &source){
+ //clock source ref 10mhz
+ switch(_mbc[mb].iface->get_rev()){
+ case usrp2_iface::USRP_N200:
+ case usrp2_iface::USRP_N210:
+ case usrp2_iface::USRP_N200_R4:
+ case usrp2_iface::USRP_N210_R4:
+ if (source == "internal") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x12);
+ else if (source == "sma") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C);
+ else if (source == "mimo") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15);
+ else throw uhd::value_error("unhandled clock configuration reference source: " + source);
+ _mbc[mb].clock->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO
+ break;
+
+ case usrp2_iface::USRP2_REV3:
+ case usrp2_iface::USRP2_REV4:
+ if (source == "internal") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x10);
+ else if (source == "sma") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C);
+ else if (source == "mimo") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15);
+ else throw uhd::value_error("unhandled clock configuration reference source: " + source);
+ _mbc[mb].clock->enable_external_ref(source != "internal");
+ break;
+
+ case usrp2_iface::USRP_NXXX: break;
+ }
+
+ //always drive the clock over serdes if not locking to it
+ _mbc[mb].clock->enable_mimo_clock_out(source != "mimo");
+
+ //set the mimo clock delay over the serdes
+ if (source != "mimo"){
+ switch(_mbc[mb].iface->get_rev()){
+ case usrp2_iface::USRP_N200:
+ case usrp2_iface::USRP_N210:
+ case usrp2_iface::USRP_N200_R4:
+ case usrp2_iface::USRP_N210_R4:
+ _mbc[mb].clock->set_mimo_clock_delay(mimo_clock_delay_usrp_n2xx);
+ break;
+
+ case usrp2_iface::USRP2_REV4:
+ _mbc[mb].clock->set_mimo_clock_delay(mimo_clock_delay_usrp2_rev4);
+ break;
+
+ default: break; //not handled
+ }
+ }
+}
diff --git a/host/lib/usrp2/usrp2_impl.hpp b/host/lib/usrp2/usrp2_impl.hpp
index a26ab455d..8ec61f739 100644
--- a/host/lib/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp2/usrp2_impl.hpp
@@ -88,7 +88,7 @@ public:
private:
uhd::property_tree::sptr _tree;
- struct mboard_stuff_type{
+ struct mb_container_type{
usrp2_iface::sptr iface;
usrp2_clock_ctrl::sptr clock;
usrp2_codec_ctrl::sptr codec;
@@ -102,14 +102,15 @@ private:
std::vector<uhd::transport::zero_copy_if::sptr> err_xports;
uhd::usrp::dboard_manager::sptr dboard_manager;
uhd::usrp::dboard_iface::sptr dboard_iface;
+ size_t rx_chan_occ, tx_chan_occ;
};
- std::vector<mboard_stuff_type> _mboard_stuff;
+ uhd::dict<std::string, mb_container_type> _mbc;
- void set_mb_eeprom(const size_t which_mb, const uhd::usrp::mboard_eeprom_t &mb_eeprom);
- void set_db_eeprom(const size_t which_mb, const std::string &type, const uhd::usrp::dboard_eeprom_t &db_eeprom);
+ void set_mb_eeprom(const std::string &, const uhd::usrp::mboard_eeprom_t &);
+ void set_db_eeprom(const std::string &, const std::string &, const uhd::usrp::dboard_eeprom_t &);
- uhd::sensor_value_t get_mimo_locked(const size_t which_mb);
- uhd::sensor_value_t get_ref_locked(const size_t which_mb);
+ uhd::sensor_value_t get_mimo_locked(const std::string &);
+ uhd::sensor_value_t get_ref_locked(const std::string &);
//device properties interface
void get(const wax::obj &, wax::obj &val){
@@ -123,8 +124,10 @@ private:
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_subdev_spec(const size_t, const uhd::usrp::subdev_spec_t &);
- void update_tx_subdev_spec(const size_t, const uhd::usrp::subdev_spec_t &);
+ void update_rx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &);
+ void update_tx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &);
+ double set_tx_dsp_freq(const std::string &, const double);
+ void update_ref_source(const std::string &, const std::string &);
};
#endif /* INCLUDED_USRP2_IMPL_HPP */