aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_200.cpp11
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_200.hpp4
-rw-r--r--host/lib/usrp/cores/tx_dsp_core_200.cpp5
-rw-r--r--host/lib/usrp/cores/tx_dsp_core_200.hpp2
-rw-r--r--host/lib/usrp2/usrp2_impl.cpp176
-rw-r--r--host/lib/usrp2/usrp2_impl.hpp13
6 files changed, 190 insertions, 21 deletions
diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp
index e4d88b38f..5aa32c630 100644
--- a/host/lib/usrp/cores/rx_dsp_core_200.cpp
+++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp
@@ -48,12 +48,11 @@ public:
rx_dsp_core_200_impl(
wb_iface::sptr iface,
const size_t dsp_base, const size_t ctrl_base,
- const boost::uint32_t sid, const size_t nsamps
+ const boost::uint32_t sid
):
_iface(iface), _dsp_base(dsp_base), _ctrl_base(ctrl_base)
{
_iface->poke32(REG_RX_CTRL_CLEAR, 1); //reset
- _iface->poke32(REG_RX_CTRL_NSAMPS_PP, nsamps);
_iface->poke32(REG_RX_CTRL_NCHANNELS, 1);
_iface->poke32(REG_RX_CTRL_VRT_HDR, 0
| (0x1 << 28) //if data with stream id
@@ -65,6 +64,10 @@ public:
_iface->poke32(REG_RX_CTRL_VRT_TLR, 0);
}
+ void set_nsamps_per_packet(const size_t nsamps){
+ _iface->poke32(REG_RX_CTRL_NSAMPS_PP, nsamps);
+ }
+
void issue_stream_command(const stream_cmd_t &stream_cmd){
UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff);
_continuous_streaming = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
@@ -159,6 +162,6 @@ private:
bool _continuous_streaming;
};
-rx_dsp_core_200::sptr rx_dsp_core_200::make(wb_iface::sptr iface, const size_t dsp_base, const size_t ctrl_base, const boost::uint32_t sid, const size_t nsamps){
- return sptr(new rx_dsp_core_200_impl(iface, dsp_base, ctrl_base, sid, nsamps));
+rx_dsp_core_200::sptr rx_dsp_core_200::make(wb_iface::sptr iface, const size_t dsp_base, const size_t ctrl_base, const boost::uint32_t sid){
+ return sptr(new rx_dsp_core_200_impl(iface, dsp_base, ctrl_base, sid));
}
diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp
index a88c39a2f..6bc7c6102 100644
--- a/host/lib/usrp/cores/rx_dsp_core_200.hpp
+++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp
@@ -32,9 +32,11 @@ public:
static sptr make(
wb_iface::sptr iface,
const size_t dsp_base, const size_t ctrl_base,
- const boost::uint32_t sid, const size_t nsamps
+ const boost::uint32_t sid
);
+ virtual void set_nsamps_per_packet(const size_t nsamps) = 0;
+
virtual void issue_stream_command(const uhd::stream_cmd_t &stream_cmd) = 0;
virtual void set_mux(const std::string &mode) = 0;
diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp
index c7e18a8a6..6ad88c380 100644
--- a/host/lib/usrp/cores/tx_dsp_core_200.cpp
+++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp
@@ -112,6 +112,11 @@ public:
return actual_freq;
}
+ void set_updates(const size_t cycles_per_up, const size_t packets_per_up){
+ _iface->poke32(REG_TX_CTRL_CYCLES_PER_UP, (cycles_per_up == 0)? 0 : (FLAG_TX_CTRL_UP_ENB | cycles_per_up));
+ _iface->poke32(REG_TX_CTRL_PACKETS_PER_UP, (packets_per_up == 0)? 0 : (FLAG_TX_CTRL_UP_ENB | packets_per_up));
+ }
+
private:
wb_iface::sptr _iface;
const size_t _dsp_base, _ctrl_base;
diff --git a/host/lib/usrp/cores/tx_dsp_core_200.hpp b/host/lib/usrp/cores/tx_dsp_core_200.hpp
index 479023caa..f218fe8c9 100644
--- a/host/lib/usrp/cores/tx_dsp_core_200.hpp
+++ b/host/lib/usrp/cores/tx_dsp_core_200.hpp
@@ -39,6 +39,8 @@ public:
virtual double set_freq(const double freq) = 0;
+ virtual void set_updates(const size_t cycles_per_up, const size_t packets_per_up) = 0;
+
};
#endif /* INCLUDED_LIBUHD_USRP_TX_DSP_CORE_200_HPP */
diff --git a/host/lib/usrp2/usrp2_impl.cpp b/host/lib/usrp2/usrp2_impl.cpp
index 9e08093dd..1ffcae626 100644
--- a/host/lib/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp2/usrp2_impl.cpp
@@ -22,18 +22,18 @@
#include <uhd/exception.hpp>
#include <uhd/transport/if_addrs.hpp>
#include <uhd/transport/udp_zero_copy.hpp>
+#include <uhd/types/ranges.hpp>
#include <uhd/usrp/device_props.hpp>
#include <uhd/exception.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/byteswap.hpp>
-#include <boost/assign/list_of.hpp>
+#include <uhd/utils/safe_call.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/asio.hpp> //used for htonl and ntohl
-#include <vector>
using namespace uhd;
using namespace uhd::usrp;
@@ -110,6 +110,23 @@ static mtu_result_t determine_mtu(const std::string &addr, const mtu_result_t &u
}
/***********************************************************************
+ * Helpers
+ **********************************************************************/
+static void init_xport(zero_copy_if::sptr xport){
+ //Send a small data packet so the usrp2 knows the udp source port.
+ //This setup must happen before further initialization occurs
+ //or the async update packets will cause ICMP destination unreachable.
+ static const boost::uint32_t data[2] = {
+ uhd::htonx(boost::uint32_t(0 /* don't care seq num */)),
+ uhd::htonx(boost::uint32_t(USRP2_INVALID_VRT_HEADER))
+ };
+
+ transport::managed_send_buffer::sptr send_buff = xport->get_send_buff();
+ std::memcpy(send_buff->cast<void*>(), &data, sizeof(data));
+ send_buff->commit(sizeof(data));
+}
+
+/***********************************************************************
* Structors
**********************************************************************/
usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
@@ -162,30 +179,102 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
_mboard_stuff.resize(device_args.size());
for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){
- property_tree::path_type mb_path = str(boost::format("/mboard%u") % mb);
- //create the iface that controls i2c, spi, uart, and wb
+ const std::string addr = device_args[mb]["addr"];
+ property_tree::path_type mb_path = str(boost::format("/mboards/%u") % 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]
+ ));
+ init_xport(_mboard_stuff[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]
+ ));
+ init_xport(_mboard_stuff[mb].dsp_xports.back());
+
+ UHD_LOG << "Making transport for ERR0..." << std::endl;
+ _mboard_stuff[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());
+
+ ////////////////////////////////////////////////////////////////
+ // create the iface that controls i2c, spi, uart, and wb
+ ////////////////////////////////////////////////////////////////
_mboard_stuff[mb].iface = usrp2_iface::make(udp_simple::make_connected(
- device_args[mb]["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)
+ addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)
));
+ _tree->create(mb_path / "name", property<std::string>(_mboard_stuff[mb].iface->get_cname()));
- //setup the mboard eeprom
- //TODO perform eeprom read here (not in iface)
- //TODO move the iface REV checks out of here
+ ////////////////////////////////////////////////////////////////
+ // setup the mboard eeprom
+ ////////////////////////////////////////////////////////////////
property<usrp::mboard_eeprom_t> mb_eeprom_prop;
mb_eeprom_prop.set(_mboard_stuff[mb].iface->mb_eeprom);
mb_eeprom_prop.subscribe(boost::bind(&usrp2_impl::set_mb_eeprom, this, mb, _1));
_tree->create(mb_path / "eeprom", mb_eeprom_prop);
- //create clock control objects
+ ////////////////////////////////////////////////////////////////
+ // create clock control objects
+ ////////////////////////////////////////////////////////////////
_mboard_stuff[mb].clock = usrp2_clock_ctrl::make(_mboard_stuff[mb].iface);
- property<double> tick_rate_prop(_mboard_stuff[mb].clock->get_master_clock_rate());
+ const double tick_rate = _mboard_stuff[mb].clock->get_master_clock_rate();
+ property<double> tick_rate_prop(tick_rate);
_tree->create(mb_path / "tick_rate", tick_rate_prop);
- //create codec control objects
+ ////////////////////////////////////////////////////////////////
+ // create codec control objects
+ ////////////////////////////////////////////////////////////////
+ property_tree::path_type rx_codec_path = mb_path / "rx_codecs/0";
+ property_tree::path_type tx_codec_path = mb_path / "tx_codecs/0";
_mboard_stuff[mb].codec = usrp2_codec_ctrl::make(_mboard_stuff[mb].iface);
+ switch(_mboard_stuff[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:{
+ _tree->create(rx_codec_path / "name", property<std::string>("ads62p44"));
+ _tree->create(rx_codec_path / "gains/0/name", property<std::string>("digital"));
+ _tree->create(rx_codec_path / "gains/0/range", property<meta_range_t>(meta_range_t(0, 6.0, 0.5)));
+ property<double> dig_gain_prop, fine_gain_prop;
+ dig_gain_prop.subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_gain, _mboard_stuff[mb].codec, _1));
+ _tree->create(rx_codec_path / "gains/0/value", dig_gain_prop);
+ _tree->create(rx_codec_path / "gains/1/name", property<std::string>("digital-fine"));
+ _tree->create(rx_codec_path / "gains/1/range", property<meta_range_t>(meta_range_t(0, 0.5, 0.05)));
+ fine_gain_prop.subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_fine_gain, _mboard_stuff[mb].codec, _1));
+ _tree->create(rx_codec_path / "gains/0/value", fine_gain_prop);
+ }break;
+
+ case usrp2_iface::USRP2_REV3:
+ case usrp2_iface::USRP2_REV4:
+ _tree->create(rx_codec_path / "name", property<std::string>("ltc2284"));
+ break;
+
+ case usrp2_iface::USRP_NXXX:
+ _tree->create(rx_codec_path / "name", property<std::string>("??????"));
+ break;
+ }
+ _tree->create(tx_codec_path / "name", property<std::string>("ad9777"));
- //create frontend control objects
+ ////////////////////////////////////////////////////////////////
+ // create gpsdo control objects
+ ////////////////////////////////////////////////////////////////
+ //TODO
+ //TODO register sensors
+
+ //TODO other sensors
+
+ //TODO clock source, time source
+
+ ////////////////////////////////////////////////////////////////
+ // 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)
);
@@ -193,14 +282,73 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
_mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_TX_FRONT)
);
- //create dsp control objects
+ ////////////////////////////////////////////////////////////////
+ // create 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), 3
+ ));
+ _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), 4
+ ));
+ for (size_t dspno = 0; dspno < _mboard_stuff[mb].rx_dsps.size(); dspno++){
+ _mboard_stuff[mb].rx_dsps[dspno]->set_tick_rate(tick_rate); //does not change on usrp2
+ property_tree::path_type rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);
+ property<double> host_rate_prop, freq_prop;
+ host_rate_prop.subscribe_master(boost::bind(&rx_dsp_core_200::set_host_rate, _mboard_stuff[mb].rx_dsps[dspno], _1));
+ _tree->create(rx_dsp_path / "rate/value", host_rate_prop);
+ freq_prop.subscribe_master(boost::bind(&rx_dsp_core_200::set_freq, _mboard_stuff[mb].rx_dsps[dspno], _1));
+ _tree->create(rx_dsp_path / "freq/value", freq_prop);
+ //TODO set nsamps per packet
+ }
+ _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), 2
+ );
+ _mboard_stuff[mb].tx_dsp->set_tick_rate(tick_rate); //does not change on usrp2
+ property<double> tx_dsp_host_rate_prop, tx_dsp_freq_prop;
+ tx_dsp_host_rate_prop.subscribe_master(boost::bind(&tx_dsp_core_200::set_host_rate, _mboard_stuff[mb].tx_dsp, _1));
+ _tree->create(mb_path / "tx_dsps/0/rate/value", tx_dsp_host_rate_prop);
+ tx_dsp_freq_prop.subscribe_master(boost::bind(&tx_dsp_core_200::set_freq, _mboard_stuff[mb].tx_dsp, _1));
+ _tree->create(mb_path / "tx_dsps/0/freq/value", tx_dsp_freq_prop);
+ //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(
+ (ups_per_sec > 0.0)? size_t(tick_rate/ups_per_sec) : 0,
+ (ups_per_fifo > 0.0)? size_t(USRP2_SRAM_BYTES/ups_per_fifo/send_frame_size) : 0
+ );
- //create time control objects
+ ////////////////////////////////////////////////////////////////
+ // create time control objects
+ ////////////////////////////////////////////////////////////////
+ time64_core_200::readback_bases_type time64_rb_bases;
+ time64_rb_bases.rb_secs_imm = U2_REG_TIME64_SECS_RB_IMM;
+ 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
+ );
+ _mboard_stuff[mb].time64->set_tick_rate(tick_rate); //does not change on usrp2
+ property<time_spec_t> time_now_prop, time_pps_prop;
+ time_now_prop.publish(boost::bind(&time64_core_200::get_time_now, _mboard_stuff[mb].time64));
+ time_now_prop.subscribe(boost::bind(&time64_core_200::set_time_now, _mboard_stuff[mb].time64, _1));
+ _tree->create(mb_path / "time/now", time_now_prop);
+ time_pps_prop.publish(boost::bind(&time64_core_200::get_time_last_pps, _mboard_stuff[mb].time64));
+ time_pps_prop.subscribe(boost::bind(&time64_core_200::set_time_next_pps, _mboard_stuff[mb].time64, _1));
+ _tree->create(mb_path / "time/pps", time_pps_prop);
}
}
+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);
+ }
+)}
+
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);
}
diff --git a/host/lib/usrp2/usrp2_impl.hpp b/host/lib/usrp2/usrp2_impl.hpp
index c3a859851..19f1d8b0f 100644
--- a/host/lib/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp2/usrp2_impl.hpp
@@ -25,6 +25,7 @@
#include "tx_frontend_core_200.hpp"
#include "rx_dsp_core_200.hpp"
#include "tx_dsp_core_200.hpp"
+#include "time64_core_200.hpp"
#include <uhd/property_tree.hpp>
#include <uhd/usrp/gps_ctrl.hpp>
#include <uhd/device.hpp>
@@ -42,6 +43,11 @@
#include <uhd/usrp/dboard_manager.hpp>
#include <uhd/usrp/subdev_spec.hpp>
+static const double mimo_clock_delay_usrp2_rev4 = 4.18e-9;
+static const double mimo_clock_delay_usrp_n2xx = 3.55e-9;
+static const size_t mimo_clock_sync_delay_cycles = 137;
+static const size_t USRP2_SRAM_BYTES = size_t(1 << 20);
+
/*!
* Make a usrp2 dboard interface.
* \param iface the usrp2 interface object
@@ -61,6 +67,7 @@ uhd::usrp::dboard_iface::sptr make_usrp2_dboard_iface(
class usrp2_impl{
public:
usrp2_impl(const uhd::device_addr_t &_device_addr);
+ ~usrp2_impl(void);
uhd::property_tree::sptr _tree;
private:
struct mboard_stuff_type{
@@ -69,9 +76,11 @@ private:
usrp2_codec_ctrl::sptr codec;
rx_frontend_core_200::sptr rx_fe;
tx_frontend_core_200::sptr tx_fe;
- rx_dsp_core_200::sptr rx_dsp;
+ std::vector<rx_dsp_core_200::sptr> rx_dsps;
tx_dsp_core_200::sptr tx_dsp;
- //TODO time core
+ time64_core_200::sptr time64;
+ std::vector<uhd::transport::zero_copy_if::sptr> dsp_xports;
+ std::vector<uhd::transport::zero_copy_if::sptr> err_xports;
};
std::vector<mboard_stuff_type> _mboard_stuff;