summaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-02-24 11:00:49 -0800
committerJosh Blum <josh@joshknows.com>2011-02-24 11:00:49 -0800
commitd588314b6f6205e0ea7051d8fc7836bdf9a6b16b (patch)
tree93ca181b6fb98cae67a639637b6911b7ebebbd73 /host
parent76ebda895cae3bd0014a5e428b07440445f3b631 (diff)
parent57b779c5103d25a94c90fd6ac465c6f7f8add9b1 (diff)
downloaduhd-d588314b6f6205e0ea7051d8fc7836bdf9a6b16b.tar.gz
uhd-d588314b6f6205e0ea7051d8fc7836bdf9a6b16b.tar.bz2
uhd-d588314b6f6205e0ea7051d8fc7836bdf9a6b16b.zip
Merge branch 'usrp2_dual_dsp' into next
Conflicts: host/include/uhd/usrp/mboard_props.hpp
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/types/device_addr.hpp10
-rw-r--r--host/include/uhd/usrp/dsp_props.hpp2
-rw-r--r--host/include/uhd/usrp/mboard_props.hpp1
-rw-r--r--host/include/uhd/usrp/multi_usrp.hpp26
-rw-r--r--host/include/uhd/usrp/tune_helper.hpp14
-rw-r--r--host/lib/transport/vrt_packet_handler.hpp4
-rw-r--r--host/lib/types/device_addr.cpp51
-rw-r--r--host/lib/usrp/multi_usrp.cpp149
-rw-r--r--host/lib/usrp/tune_helper.cpp29
-rw-r--r--host/lib/usrp/usrp1/dsp_impl.cpp95
-rw-r--r--host/lib/usrp/usrp1/mboard_impl.cpp14
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.hpp16
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp161
-rw-r--r--host/lib/usrp/usrp2/fw_common.h7
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp119
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp174
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp144
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp70
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.cpp51
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.hpp40
-rw-r--r--host/lib/usrp/usrp_e100/dsp_impl.cpp14
-rw-r--r--host/lib/usrp/usrp_e100/mboard_impl.cpp4
-rw-r--r--host/tests/tune_helper_test.cpp22
23 files changed, 633 insertions, 584 deletions
diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp
index eb3394230..2c0841146 100644
--- a/host/include/uhd/types/device_addr.hpp
+++ b/host/include/uhd/types/device_addr.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -84,9 +84,15 @@ namespace uhd{
}
};
- //handy typedef for a vector of device addresses
+ //! A typedef for a vector of device addresses
typedef std::vector<device_addr_t> device_addrs_t;
+ //! Separate an indexed device address into a vector of device addresses
+ UHD_API device_addrs_t separate_device_addr(const device_addr_t &dev_addr);
+
+ //! Combine a vector of device addresses into an indexed device address
+ UHD_API device_addr_t combine_device_addrs(const device_addrs_t &dev_addrs);
+
} //namespace uhd
#endif /* INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP */
diff --git a/host/include/uhd/usrp/dsp_props.hpp b/host/include/uhd/usrp/dsp_props.hpp
index 3e1690317..e68e11deb 100644
--- a/host/include/uhd/usrp/dsp_props.hpp
+++ b/host/include/uhd/usrp/dsp_props.hpp
@@ -39,8 +39,8 @@ namespace uhd{ namespace usrp{
enum dsp_prop_t{
DSP_PROP_NAME, //ro, std::string
DSP_PROP_OTHERS, //ro, prop_names_t
+ DSP_PROP_STREAM_CMD, //wo, stream_cmd_t
DSP_PROP_FREQ_SHIFT, //rw, double Hz
- DSP_PROP_FREQ_SHIFT_NAMES, //ro, prop_names_t
DSP_PROP_CODEC_RATE, //ro, double Sps
DSP_PROP_HOST_RATE //rw, double Sps
};
diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp
index 8855e2b75..180c4eeb3 100644
--- a/host/include/uhd/usrp/mboard_props.hpp
+++ b/host/include/uhd/usrp/mboard_props.hpp
@@ -47,7 +47,6 @@ namespace uhd{ namespace usrp{
MBOARD_PROP_CLOCK_CONFIG, //rw, clock_config_t
MBOARD_PROP_TIME_NOW, //rw, time_spec_t
MBOARD_PROP_TIME_PPS, //wo, time_spec_t
- MBOARD_PROP_STREAM_CMD, //wo, stream_cmd_t
MBOARD_PROP_EEPROM_MAP //wr, mboard_eeprom_t
};
diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp
index 3c8dd5fac..b06975b6c 100644
--- a/host/include/uhd/usrp/multi_usrp.hpp
+++ b/host/include/uhd/usrp/multi_usrp.hpp
@@ -87,6 +87,9 @@ public:
//! A wildcard motherboard index
static const size_t ALL_MBOARDS = size_t(~0);
+ //! A wildcard channel index
+ static const size_t ALL_CHANS = size_t(~0);
+
//! A wildcard gain element name
static const std::string ALL_GAINS;
@@ -215,8 +218,9 @@ public:
* to ensure that the packets can be aligned by their time specs.
*
* \param stream_cmd the stream command to issue
+ * \param chan the channel index 0 to N-1
*/
- virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0;
+ virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan = ALL_CHANS) = 0;
/*!
* Set the clock configuration for the usrp device.
@@ -282,16 +286,18 @@ public:
virtual std::string get_rx_subdev_name(size_t chan = 0) = 0;
/*!
- * Set the RX sample rate across all channels.
+ * Set the RX sample rate.
* \param rate the rate in Sps
+ * \param chan the channel index 0 to N-1
*/
- virtual void set_rx_rate(double rate) = 0;
+ virtual void set_rx_rate(double rate, size_t chan = ALL_CHANS) = 0;
/*!
- * Gets the RX sample rate for all channels.
+ * Gets the RX sample rate.
+ * \param chan the channel index 0 to N-1
* \return the rate in Sps
*/
- virtual double get_rx_rate(void) = 0;
+ virtual double get_rx_rate(size_t chan = 0) = 0;
/*!
* Set the RX center frequency.
@@ -480,16 +486,18 @@ public:
virtual std::string get_tx_subdev_name(size_t chan = 0) = 0;
/*!
- * Set the TX sample rate across all channels.
+ * Set the TX sample rate.
* \param rate the rate in Sps
+ * \param chan the channel index 0 to N-1
*/
- virtual void set_tx_rate(double rate) = 0;
+ virtual void set_tx_rate(double rate, size_t chan = ALL_CHANS) = 0;
/*!
- * Gets the TX sample rate for all channels.
+ * Gets the TX sample rate.
+ * \param chan the channel index 0 to N-1
* \return the rate in Sps
*/
- virtual double get_tx_rate(void) = 0;
+ virtual double get_tx_rate(size_t chan = 0) = 0;
/*!
* Set the TX center frequency.
diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp
index db12241c1..e97ab0298 100644
--- a/host/include/uhd/usrp/tune_helper.hpp
+++ b/host/include/uhd/usrp/tune_helper.hpp
@@ -32,24 +32,21 @@ namespace uhd{ namespace usrp{
* The ddc cordic is setup to bring the IF down to baseband.
* \param subdev the dboard subdevice object with properties
* \param ddc the mboard dsp object with properties
- * \param chan the channel of the dsp to tune
* \param tune_request tune request instructions
* \return a tune result struct
*/
UHD_API tune_result_t tune_rx_subdev_and_dsp(
- wax::obj subdev, wax::obj ddc, size_t chan,
- const tune_request_t &tune_request
+ wax::obj subdev, wax::obj ddc, const tune_request_t &tune_request
);
/*!
* Calculate the overall frequency from the combination of dboard IF and DDC shift.
* \param subdev the dboard subdevice object with properties
* \param ddc the mboard dsp object with properties
- * \param chan the channel of the dsp to tune
* \return the overall tune frequency of the system in Hz
*/
UHD_API double derive_freq_from_rx_subdev_and_dsp(
- wax::obj subdev, wax::obj ddc, size_t chan
+ wax::obj subdev, wax::obj ddc
);
/*!
@@ -59,24 +56,21 @@ namespace uhd{ namespace usrp{
* The duc cordic is setup to bring the baseband up to IF.
* \param subdev the dboard subdevice object with properties
* \param duc the mboard dsp object with properties
- * \param chan the channel of the dsp to tune
* \param tune_request tune request instructions
* \return a tune result struct
*/
UHD_API tune_result_t tune_tx_subdev_and_dsp(
- wax::obj subdev, wax::obj duc, size_t chan,
- const tune_request_t &tune_request
+ wax::obj subdev, wax::obj duc, const tune_request_t &tune_request
);
/*!
* Calculate the overall frequency from the combination of dboard IF and DUC shift.
* \param subdev the dboard subdevice object with properties
* \param duc the mboard dsp object with properties
- * \param chan the channel of the dsp to tune
* \return the overall tune frequency of the system in Hz
*/
UHD_API double derive_freq_from_tx_subdev_and_dsp(
- wax::obj subdev, wax::obj duc, size_t chan
+ wax::obj subdev, wax::obj duc
);
}}
diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp
index 6f3ac0421..4f8ce7e52 100644
--- a/host/lib/transport/vrt_packet_handler.hpp
+++ b/host/lib/transport/vrt_packet_handler.hpp
@@ -300,18 +300,18 @@ template <typename T> UHD_INLINE T get_context_code(
typedef boost::function<bool(managed_send_buffs_t &)> get_send_buffs_t;
typedef boost::function<void(boost::uint32_t *, uhd::transport::vrt::if_packet_info_t &)> vrt_packer_t;
+ static const boost::uint64_t zeros = 0;
+
struct send_state{
//init the expected seq number
size_t next_packet_seq;
managed_send_buffs_t managed_buffs;
- const boost::uint64_t zeros;
std::vector<const void *> zero_buffs;
std::vector<const void *> io_buffs;
send_state(size_t width = 1):
next_packet_seq(0),
managed_buffs(width),
- zeros(0),
zero_buffs(width, &zeros),
io_buffs(0) //resized later
{
diff --git a/host/lib/types/device_addr.cpp b/host/lib/types/device_addr.cpp
index 14afaa24b..7f2031272 100644
--- a/host/lib/types/device_addr.cpp
+++ b/host/lib/types/device_addr.cpp
@@ -16,10 +16,11 @@
//
#include <uhd/types/device_addr.hpp>
-#include <boost/algorithm/string.hpp> //for trim
+#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
+#include <boost/regex.hpp>
#include <stdexcept>
#include <sstream>
@@ -71,3 +72,51 @@ std::string device_addr_t::to_string(void) const{
}
return args_str;
}
+
+#include <uhd/utils/warning.hpp>
+
+device_addrs_t uhd::separate_device_addr(const device_addr_t &dev_addr){
+ //------------ support old deprecated way and print warning --------
+ if (dev_addr.has_key("addr") and not dev_addr["addr"].empty()){
+ std::vector<std::string> addrs; boost::split(addrs, dev_addr["addr"], boost::is_any_of(" "));
+ if (addrs.size() > 1){
+ device_addr_t fixed_dev_addr = dev_addr;
+ fixed_dev_addr.pop("addr");
+ for (size_t i = 0; i < addrs.size(); i++){
+ fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i];
+ }
+ uhd::warning::post(
+ "addr = <space separated list of ip addresses> is deprecated.\n"
+ "To address a multi-device, use multiple <key><index> = <val>.\n"
+ "See the USRP-NXXX application notes. Two device example:\n"
+ " addr0 = 192.168.10.2\n"
+ " addr1 = 192.168.10.3\n"
+ );
+ return separate_device_addr(fixed_dev_addr);
+ }
+ }
+ //------------------------------------------------------------------
+ device_addrs_t dev_addrs;
+ BOOST_FOREACH(const std::string &key, dev_addr.keys()){
+ boost::cmatch matches;
+ if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){
+ throw std::runtime_error("unknown key format: " + key);
+ }
+ std::string key_part(matches[1].first, matches[1].second);
+ std::string num_part(matches[2].first, matches[2].second);
+ size_t num = (num_part.empty())? 0 : boost::lexical_cast<size_t>(num_part);
+ dev_addrs.resize(std::max(num+1, dev_addrs.size()));
+ dev_addrs[num][key_part] = dev_addr[key];
+ }
+ return dev_addrs;
+}
+
+device_addr_t uhd::combine_device_addrs(const device_addrs_t &dev_addrs){
+ device_addr_t dev_addr;
+ for (size_t i = 0; i < dev_addrs.size(); i++){
+ BOOST_FOREACH(const std::string &key, dev_addrs[i].keys()){
+ dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key];
+ }
+ }
+ return dev_addr;
+}
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 73bac029d..23049d569 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -85,17 +85,14 @@ public:
//----------- rx side of life ----------------------------------
for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){
- buff += str(boost::format(
- " RX DSP %d: %s\n"
- ) % m
- % _rx_dsp(m)[DSP_PROP_NAME].as<std::string>()
- );
for (; chan < (m + 1)*get_rx_subdev_spec(m).size(); chan++){
buff += str(boost::format(
" RX Channel: %u\n"
+ " RX DSP: %s\n"
" RX Dboard: %s\n"
" RX Subdev: %s\n"
) % chan
+ % _rx_dsp(chan)[DSP_PROP_NAME].as<std::string>()
% _rx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>()
% _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>()
);
@@ -104,17 +101,14 @@ public:
//----------- tx side of life ----------------------------------
for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){
- buff += str(boost::format(
- " TX DSP %d: %s\n"
- ) % m
- % _tx_dsp(m)[DSP_PROP_NAME].as<std::string>()
- );
for (; chan < (m + 1)*get_tx_subdev_spec(m).size(); chan++){
buff += str(boost::format(
" TX Channel: %u\n"
+ " TX DSP: %s\n"
" TX Dboard: %s\n"
" TX Subdev: %s\n"
) % chan
+ % _tx_dsp(chan)[DSP_PROP_NAME].as<std::string>()
% _tx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>()
% _tx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>()
);
@@ -194,9 +188,13 @@ public:
return true;
}
- void issue_stream_cmd(const stream_cmd_t &stream_cmd){
- for (size_t m = 0; m < get_num_mboards(); m++){
- _mboard(m)[MBOARD_PROP_STREAM_CMD] = stream_cmd;
+ void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan){
+ if (chan != ALL_CHANS){
+ _rx_dsp(chan)[DSP_PROP_STREAM_CMD] = stream_cmd;
+ return;
+ }
+ for (size_t c = 0; c < get_rx_num_channels(); c++){
+ issue_stream_cmd(stream_cmd, c);
}
}
@@ -240,36 +238,44 @@ public:
}
size_t get_rx_num_channels(void){
- return rx_cpm()*get_num_mboards(); //total num channels
+ size_t sum = 0;
+ for (size_t m = 0; m < get_num_mboards(); m++){
+ sum += get_rx_subdev_spec(m).size();
+ }
+ return sum;
}
std::string get_rx_subdev_name(size_t chan){
return _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>();
}
- void set_rx_rate(double rate){
- for (size_t m = 0; m < get_num_mboards(); m++){
- _rx_dsp(m)[DSP_PROP_HOST_RATE] = rate;
+ void set_rx_rate(double rate, size_t chan){
+ if (chan != ALL_CHANS){
+ _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate;
+ do_samp_rate_warning_message(rate, get_rx_rate(chan), "RX");
+ return;
+ }
+ for (size_t c = 0; c < get_rx_num_channels(); c++){
+ set_rx_rate(rate, c);
}
- do_samp_rate_warning_message(rate, get_rx_rate(), "RX");
}
- double get_rx_rate(void){
- return _rx_dsp(0)[DSP_PROP_HOST_RATE].as<double>();
+ double get_rx_rate(size_t chan){
+ return _rx_dsp(chan)[DSP_PROP_HOST_RATE].as<double>();
}
tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){
- tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), tune_request);
+ tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), tune_request);
do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX");
return r;
}
double get_rx_freq(size_t chan){
- return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm());
+ return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan));
}
freq_range_t get_rx_freq_range(size_t chan){
- return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan/rx_cpm()));
+ return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan));
}
void set_rx_gain(double gain, const std::string &name, size_t chan){
@@ -342,32 +348,40 @@ public:
}
size_t get_tx_num_channels(void){
- return tx_cpm()*get_num_mboards(); //total num channels
+ size_t sum = 0;
+ for (size_t m = 0; m < get_num_mboards(); m++){
+ sum += get_tx_subdev_spec(m).size();
+ }
+ return sum;
}
- void set_tx_rate(double rate){
- for (size_t m = 0; m < get_num_mboards(); m++){
- _tx_dsp(m)[DSP_PROP_HOST_RATE] = rate;
+ void set_tx_rate(double rate, size_t chan){
+ if (chan != ALL_CHANS){
+ _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate;
+ do_samp_rate_warning_message(rate, get_tx_rate(chan), "TX");
+ return;
+ }
+ for (size_t c = 0; c < get_tx_num_channels(); c++){
+ set_tx_rate(rate, c);
}
- do_samp_rate_warning_message(rate, get_tx_rate(), "TX");
}
- double get_tx_rate(void){
- return _tx_dsp(0)[DSP_PROP_HOST_RATE].as<double>();
+ double get_tx_rate(size_t chan){
+ return _tx_dsp(chan)[DSP_PROP_HOST_RATE].as<double>();
}
tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){
- tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), tune_request);
+ tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), tune_request);
do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX");
return r;
}
double get_tx_freq(size_t chan){
- return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm());
+ return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan));
}
freq_range_t get_tx_freq_range(size_t chan){
- return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan/tx_cpm()));
+ return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan));
}
void set_tx_gain(double gain, const std::string &name, size_t chan){
@@ -421,58 +435,75 @@ public:
private:
device::sptr _dev;
- size_t rx_cpm(void){ //channels per mboard
- size_t nchan = get_rx_subdev_spec(0).size();
- for (size_t m = 1; m < get_num_mboards(); m++){
- if (nchan != get_rx_subdev_spec(m).size()){
- throw std::runtime_error("rx subdev spec size inconsistent across all mboards");
- }
+ struct mboard_chan_pair{
+ size_t mboard, chan;
+ mboard_chan_pair(void): mboard(0), chan(0){}
+ };
+
+ mboard_chan_pair rx_chan_to_mcp(size_t chan){
+ mboard_chan_pair mcp;
+ mcp.chan = chan;
+ for (mcp.mboard = 0; mcp.mboard < get_num_mboards(); mcp.mboard++){
+ size_t sss = get_rx_subdev_spec(mcp.mboard).size();
+ if (mcp.chan < sss) break;
+ mcp.chan -= sss;
}
- return nchan;
+ return mcp;
}
- size_t tx_cpm(void){ //channels per mboard
- size_t nchan = get_tx_subdev_spec(0).size();
- for (size_t m = 1; m < get_num_mboards(); m++){
- if (nchan != get_tx_subdev_spec(m).size()){
- throw std::runtime_error("tx subdev spec size inconsistent across all mboards");
- }
+ mboard_chan_pair tx_chan_to_mcp(size_t chan){
+ mboard_chan_pair mcp;
+ mcp.chan = chan;
+ for (mcp.mboard = 0; mcp.mboard < get_num_mboards(); mcp.mboard++){
+ size_t sss = get_tx_subdev_spec(mcp.mboard).size();
+ if (mcp.chan < sss) break;
+ mcp.chan -= sss;
}
- return nchan;
+ return mcp;
}
wax::obj _mboard(size_t mboard){
std::string mb_name = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>().at(mboard);
return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, mb_name)];
}
- wax::obj _rx_dsp(size_t mboard){
- return _mboard(mboard)[MBOARD_PROP_RX_DSP];
+ wax::obj _rx_dsp(size_t chan){
+ mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ prop_names_t dsp_names = _mboard(mcp.mboard)[MBOARD_PROP_RX_DSP_NAMES].as<prop_names_t>();
+ return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_RX_DSP, dsp_names.at(mcp.chan))];
}
- wax::obj _tx_dsp(size_t mboard){
- return _mboard(mboard)[MBOARD_PROP_TX_DSP];
+ wax::obj _tx_dsp(size_t chan){
+ mboard_chan_pair mcp = tx_chan_to_mcp(chan);
+ prop_names_t dsp_names = _mboard(mcp.mboard)[MBOARD_PROP_TX_DSP_NAMES].as<prop_names_t>();
+ return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_TX_DSP, dsp_names.at(mcp.chan))];
}
wax::obj _rx_dboard(size_t chan){
- std::string db_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).db_name;
- return _mboard(chan/rx_cpm())[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)];
+ mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ std::string db_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).db_name;
+ return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)];
}
wax::obj _tx_dboard(size_t chan){
- std::string db_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).db_name;
- return _mboard(chan/tx_cpm())[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)];
+ mboard_chan_pair mcp = tx_chan_to_mcp(chan);
+ std::string db_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).db_name;
+ return _mboard(mcp.mboard)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)];
}
wax::obj _rx_subdev(size_t chan){
- std::string sd_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).sd_name;
+ mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ std::string sd_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name;
return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)];
}
wax::obj _tx_subdev(size_t chan){
- std::string sd_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).sd_name;
+ mboard_chan_pair mcp = tx_chan_to_mcp(chan);
+ std::string sd_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name;
return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)];
}
gain_group::sptr _rx_gain_group(size_t chan){
- std::string sd_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).sd_name;
+ mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ std::string sd_name = get_rx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name;
return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>();
}
gain_group::sptr _tx_gain_group(size_t chan){
- std::string sd_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).sd_name;
+ mboard_chan_pair mcp = tx_chan_to_mcp(chan);
+ std::string sd_name = get_tx_subdev_spec(mcp.mboard).at(mcp.chan).sd_name;
return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>();
}
};
diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp
index eccee7f4b..ced80c187 100644
--- a/host/lib/usrp/tune_helper.cpp
+++ b/host/lib/usrp/tune_helper.cpp
@@ -30,12 +30,11 @@ using namespace uhd::usrp;
**********************************************************************/
static tune_result_t tune_xx_subdev_and_dsp(
dboard_iface::unit_t unit,
- wax::obj subdev, wax::obj dsp, size_t chan,
+ wax::obj subdev, wax::obj dsp,
const tune_request_t &tune_request
){
wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
- std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan);
- wax::obj dsp_freq_proxy = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)];
+ wax::obj dsp_freq_proxy = dsp[DSP_PROP_FREQ_SHIFT];
//------------------------------------------------------------------
//-- calculate the LO offset, only used with automatic policy
@@ -105,13 +104,11 @@ static tune_result_t tune_xx_subdev_and_dsp(
}
static double derive_freq_from_xx_subdev_and_dsp(
- dboard_iface::unit_t unit,
- wax::obj subdev, wax::obj dsp, size_t chan
+ dboard_iface::unit_t unit, wax::obj subdev, wax::obj dsp
){
//extract actual dsp and IF frequencies
double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as<double>();
- std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan);
- double actual_dsp_freq = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as<double>();
+ double actual_dsp_freq = dsp[DSP_PROP_FREQ_SHIFT].as<double>();
//invert the sign on the dsp freq given the following conditions
if (unit == dboard_iface::UNIT_TX) actual_dsp_freq *= -1.0;
@@ -123,30 +120,28 @@ static double derive_freq_from_xx_subdev_and_dsp(
* RX Tune
**********************************************************************/
tune_result_t usrp::tune_rx_subdev_and_dsp(
- wax::obj subdev, wax::obj ddc, size_t chan,
- const tune_request_t &tune_request
+ wax::obj subdev, wax::obj ddc, const tune_request_t &tune_request
){
- return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan, tune_request);
+ return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, tune_request);
}
double usrp::derive_freq_from_rx_subdev_and_dsp(
- wax::obj subdev, wax::obj ddc, size_t chan
+ wax::obj subdev, wax::obj ddc
){
- return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan);
+ return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc);
}
/***********************************************************************
* TX Tune
**********************************************************************/
tune_result_t usrp::tune_tx_subdev_and_dsp(
- wax::obj subdev, wax::obj duc, size_t chan,
- const tune_request_t &tune_request
+ wax::obj subdev, wax::obj duc, const tune_request_t &tune_request
){
- return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan, tune_request);
+ return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, tune_request);
}
double usrp::derive_freq_from_tx_subdev_and_dsp(
- wax::obj subdev, wax::obj duc, size_t chan
+ wax::obj subdev, wax::obj duc
){
- return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan);
+ return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc);
}
diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp
index 370f4831f..8152c4e34 100644
--- a/host/lib/usrp/usrp1/dsp_impl.cpp
+++ b/host/lib/usrp/usrp1/dsp_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -34,23 +34,25 @@ using namespace uhd::usrp;
**********************************************************************/
void usrp1_impl::rx_dsp_init(void)
{
- _rx_dsp_proxy = wax_obj_proxy::make(
- boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2),
- boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2));
-
- rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16);
+ for (size_t i = 0; i < this->get_num_ddcs(); i++){
+ _rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2, i),
+ boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2, i)
+ );
+ rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16, i);
+ }
}
/***********************************************************************
* RX DDC Get
**********************************************************************/
-void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){
+void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){
named_prop_t key = named_prop_t::extract(key_);
switch(key.as<dsp_prop_t>()){
case DSP_PROP_NAME:
- val = str(boost::format("usrp1 ddc %uX %s")
- % this->get_num_ddcs()
+ val = str(boost::format("usrp1 ddc%d %s")
+ % which_dsp
% (this->has_rx_halfband()? "+ hb" : "")
);
return;
@@ -60,16 +62,7 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){
return;
case DSP_PROP_FREQ_SHIFT:
- val = _rx_dsp_freqs[key.name];
- return;
-
- case DSP_PROP_FREQ_SHIFT_NAMES:{
- prop_names_t names;
- for(size_t i = 0; i < this->get_num_ddcs(); i++){
- names.push_back(boost::lexical_cast<std::string>(i));
- }
- val = names;
- }
+ val = _rx_dsp_freqs[which_dsp];
return;
case DSP_PROP_CODEC_RATE:
@@ -88,7 +81,7 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){
/***********************************************************************
* RX DDC Set
**********************************************************************/
-void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){
+void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){
named_prop_t key = named_prop_t::extract(key_);
switch(key.as<dsp_prop_t>()) {
@@ -97,16 +90,17 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){
boost::uint32_t reg_word = dsp_type1::calc_cordic_word_and_update(
new_freq, _clock_ctrl->get_master_clock_freq());
- static const uhd::dict<std::string, boost::uint32_t>
- freq_name_to_reg_val = boost::assign::map_list_of
- ("0", FR_RX_FREQ_0) ("1", FR_RX_FREQ_1)
- ("2", FR_RX_FREQ_2) ("3", FR_RX_FREQ_3)
- ;
- _iface->poke32(freq_name_to_reg_val[key.name], ~reg_word + 1);
- _rx_dsp_freqs[key.name] = new_freq;
+ static const boost::uint32_t dsp_index_to_reg_val[4] = {
+ FR_RX_FREQ_0, FR_RX_FREQ_1, FR_RX_FREQ_2, FR_RX_FREQ_3
+ };
+ _iface->poke32(dsp_index_to_reg_val[which_dsp], ~reg_word + 1);
+ _rx_dsp_freqs[which_dsp] = new_freq;
return;
}
- case DSP_PROP_HOST_RATE: {
+
+ case DSP_PROP_HOST_RATE:
+ if (which_dsp != 0) return; //only for dsp[0] as this is vectorized
+ {
size_t rate = size_t(_clock_ctrl->get_master_clock_freq() / val.as<double>());
if ((rate & 0x01) || (rate < 4) || (rate > 256)) {
@@ -123,6 +117,11 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){
}
return;
+ case DSP_PROP_STREAM_CMD:
+ if (which_dsp != 0) return; //only for dsp[0] as this is vectorized
+ _soft_time_ctrl->issue_stream_cmd(val.as<stream_cmd_t>());
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
@@ -133,24 +132,25 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){
**********************************************************************/
void usrp1_impl::tx_dsp_init(void)
{
- _tx_dsp_proxy = wax_obj_proxy::make(
- boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2),
- boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2));
-
- //initial config and update
- tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() * 2 / 16);
+ for (size_t i = 0; i < this->get_num_ducs(); i++){
+ _tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2, i),
+ boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2, i)
+ );
+ tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16, i);
+ }
}
/***********************************************************************
* TX DUC Get
**********************************************************************/
-void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){
+void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){
named_prop_t key = named_prop_t::extract(key_);
switch(key.as<dsp_prop_t>()) {
case DSP_PROP_NAME:
- val = str(boost::format("usrp1 duc %uX %s")
- % this->get_num_ducs()
+ val = str(boost::format("usrp1 duc%d %s")
+ % which_dsp
% (this->has_tx_halfband()? "+ hb" : "")
);
return;
@@ -160,16 +160,7 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){
return;
case DSP_PROP_FREQ_SHIFT:
- val = _tx_dsp_freqs[key.name];
- return;
-
- case DSP_PROP_FREQ_SHIFT_NAMES:{
- prop_names_t names;
- for(size_t i = 0; i < this->get_num_ducs(); i++){
- names.push_back(boost::lexical_cast<std::string>(i));
- }
- val = names;
- }
+ val = _tx_dsp_freqs[which_dsp];
return;
case DSP_PROP_CODEC_RATE:
@@ -188,7 +179,7 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){
/***********************************************************************
* TX DUC Set
**********************************************************************/
-void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){
+void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){
named_prop_t key = named_prop_t::extract(key_);
switch(key.as<dsp_prop_t>()) {
@@ -197,15 +188,17 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){
double new_freq = val.as<double>();
//map the freq shift key to a subdev spec to a particular codec chip
- std::string db_name = _tx_subdev_spec.at(boost::lexical_cast<size_t>(key.name)).db_name;
+ std::string db_name = _tx_subdev_spec.at(which_dsp).db_name;
if (db_name == "A") _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq);
if (db_name == "B") _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq);
- _tx_dsp_freqs[key.name] = new_freq;
+ _tx_dsp_freqs[which_dsp] = new_freq;
return;
}
- case DSP_PROP_HOST_RATE: {
+ case DSP_PROP_HOST_RATE:
+ if (which_dsp != 0) return; //only for dsp[0] as this is vectorized
+ {
size_t rate = size_t(_clock_ctrl->get_master_clock_freq() * 2 / val.as<double>());
if ((rate & 0x01) || (rate < 8) || (rate > 512)) {
diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp
index 6d5bf466d..26d3e41d4 100644
--- a/host/lib/usrp/usrp1/mboard_impl.cpp
+++ b/host/lib/usrp/usrp1/mboard_impl.cpp
@@ -280,21 +280,19 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val)
return;
case MBOARD_PROP_RX_DSP:
- UHD_ASSERT_THROW(key.name == "");
- val = _rx_dsp_proxy->get_link();
+ val = _rx_dsp_proxies.get(key.name)->get_link();
return;
case MBOARD_PROP_RX_DSP_NAMES:
- val = prop_names_t(1, "");
+ val = _rx_dsp_proxies.keys();
return;
case MBOARD_PROP_TX_DSP:
- UHD_ASSERT_THROW(key.name == "");
- val = _tx_dsp_proxy->get_link();
+ val = _tx_dsp_proxies.get(key.name)->get_link();
return;
case MBOARD_PROP_TX_DSP_NAMES:
- val = prop_names_t(1, "");
+ val = _tx_dsp_proxies.keys();
return;
case MBOARD_PROP_CLOCK_CONFIG:
@@ -342,10 +340,6 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
- case MBOARD_PROP_STREAM_CMD:
- _soft_time_ctrl->issue_stream_cmd(val.as<stream_cmd_t>());
- return;
-
case MBOARD_PROP_RX_SUBDEV_SPEC:
_rx_subdev_spec = val.as<subdev_spec_t>();
if (_rx_subdev_spec.size() > this->get_num_ddcs()){
diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp
index 1d9f6709f..9755c466d 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.hpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.hpp
@@ -182,19 +182,19 @@ private:
//rx dsp functions and settings
void rx_dsp_init(void);
- void rx_dsp_get(const wax::obj &, wax::obj &);
- void rx_dsp_set(const wax::obj &, const wax::obj &);
- uhd::dict<std::string, double> _rx_dsp_freqs;
+ void rx_dsp_get(const wax::obj &, wax::obj &, size_t);
+ void rx_dsp_set(const wax::obj &, const wax::obj &, size_t);
+ uhd::dict<size_t, double> _rx_dsp_freqs;
size_t _rx_dsp_decim;
- wax_obj_proxy::sptr _rx_dsp_proxy;
+ uhd::dict<std::string, wax_obj_proxy::sptr> _rx_dsp_proxies;
//tx dsp functions and settings
void tx_dsp_init(void);
- void tx_dsp_get(const wax::obj &, wax::obj &);
- void tx_dsp_set(const wax::obj &, const wax::obj &);
- uhd::dict<std::string, double> _tx_dsp_freqs;
+ void tx_dsp_get(const wax::obj &, wax::obj &, size_t);
+ void tx_dsp_set(const wax::obj &, const wax::obj &, size_t);
+ uhd::dict<size_t, double> _tx_dsp_freqs;
size_t _tx_dsp_interp;
- wax_obj_proxy::sptr _tx_dsp_proxy;
+ uhd::dict<std::string, wax_obj_proxy::sptr> _tx_dsp_proxies;
//transports
uhd::transport::usb_zero_copy::sptr _data_transport;
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 8340f7cdd..cdd559e94 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -28,12 +28,79 @@
using namespace uhd;
using namespace uhd::usrp;
-static const size_t default_decim = 16;
-static const size_t default_interp = 16;
-
/***********************************************************************
- * DDC Helper Methods
+ * DSP impl and methods
**********************************************************************/
+struct usrp2_mboard_impl::dsp_impl{
+ uhd::dict<size_t, size_t> ddc_decim;
+ uhd::dict<size_t, double> ddc_freq;
+ uhd::dict<size_t, size_t> duc_interp;
+ uhd::dict<size_t, double> duc_freq;
+ std::vector<size_t> decim_and_interp_rates;
+ uhd::dict<size_t, bool> continuous_streaming;
+};
+
+void usrp2_mboard_impl::dsp_init(void){
+ //create new dsp impl
+ _dsp_impl = UHD_PIMPL_MAKE(dsp_impl, ());
+
+ //load the allowed decim/interp rates
+ //range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4)
+ for (size_t i = 4; i <= 128; i+=1){
+ _dsp_impl->decim_and_interp_rates.push_back(i);
+ }
+ for (size_t i = 130; i <= 256; i+=2){
+ _dsp_impl->decim_and_interp_rates.push_back(i);
+ }
+ for (size_t i = 260; i <= 512; i+=4){
+ _dsp_impl->decim_and_interp_rates.push_back(i);
+ }
+
+ //bind and initialize the rx dsps
+ for (size_t i = 0; i < NUM_RX_DSPS; i++){
+ _rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make(
+ boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2, i),
+ boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2, i)
+ );
+
+ //initial config and update
+ ddc_set(DSP_PROP_FREQ_SHIFT, double(0), i);
+ ddc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/16), i);
+
+ //setup the rx control registers
+ _iface->poke32(_iface->regs.rx_ctrl[i].clear_overrun, 1); //reset
+ _iface->poke32(_iface->regs.rx_ctrl[i].nsamps_per_pkt, _device.get_max_recv_samps_per_packet());
+ _iface->poke32(_iface->regs.rx_ctrl[i].nchannels, 1);
+ _iface->poke32(_iface->regs.rx_ctrl[i].vrt_header, 0
+ | (0x1 << 28) //if data with stream id
+ | (0x1 << 26) //has trailer
+ | (0x3 << 22) //integer time other
+ | (0x1 << 20) //fractional time sample count
+ );
+ _iface->poke32(_iface->regs.rx_ctrl[i].vrt_stream_id, usrp2_impl::RECV_SID);
+ _iface->poke32(_iface->regs.rx_ctrl[i].vrt_trailer, 0);
+ _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq()));
+ }
+
+ //bind and initialize the tx dsps
+ for (size_t i = 0; i < NUM_TX_DSPS; i++){
+ _tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make(
+ boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2, i),
+ boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2, i)
+ );
+
+ //initial config and update
+ duc_set(DSP_PROP_FREQ_SHIFT, double(0), i);
+ duc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/16), i);
+
+ //init the tx control registers
+ _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset
+ _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0); //1 channel
+ _iface->poke32(_iface->regs.tx_ctrl_report_sid, usrp2_impl::ASYNC_SID);
+ _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET);
+ }
+}
+
template <typename rate_type>
static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_type> &rates){
unsigned closest_match = rates.front();
@@ -44,27 +111,28 @@ static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_typ
return closest_match;
}
-void usrp2_mboard_impl::init_ddc_config(void){
- //create the ddc in the rx dsp dict
- _rx_dsp_proxy = wax_obj_proxy::make(
- boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2),
- boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2)
- );
+void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd, size_t which_dsp){
+ _dsp_impl->continuous_streaming[which_dsp] = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
+ _iface->poke32(_iface->regs.rx_ctrl[which_dsp].stream_cmd, dsp_type1::calc_stream_cmd_word(stream_cmd));
+ _iface->poke32(_iface->regs.rx_ctrl[which_dsp].time_secs, boost::uint32_t(stream_cmd.time_spec.get_full_secs()));
+ _iface->poke32(_iface->regs.rx_ctrl[which_dsp].time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq()));
+}
- //initial config and update
- ddc_set(DSP_PROP_FREQ_SHIFT, double(0));
- ddc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/default_decim));
+void usrp2_mboard_impl::handle_overflow(size_t which_dsp){
+ if (_dsp_impl->continuous_streaming[which_dsp]){ //re-issue the stream command if already continuous
+ this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS, which_dsp);
+ }
}
/***********************************************************************
* DDC Properties
**********************************************************************/
-void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){
+void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){
named_prop_t key = named_prop_t::extract(key_);
switch(key.as<dsp_prop_t>()){
case DSP_PROP_NAME:
- val = _iface->get_cname() + " ddc0";
+ val = str(boost::format("%s ddc%d") % _iface->get_cname() % which_dsp);
return;
case DSP_PROP_OTHERS:
@@ -72,11 +140,7 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){
return;
case DSP_PROP_FREQ_SHIFT:
- val = _ddc_freq;
- return;
-
- case DSP_PROP_FREQ_SHIFT_NAMES:
- val = prop_names_t(1, "");
+ val = _dsp_impl->ddc_freq[which_dsp];
return;
case DSP_PROP_CODEC_RATE:
@@ -84,37 +148,41 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){
return;
case DSP_PROP_HOST_RATE:
- val = get_master_clock_freq()/_ddc_decim;
+ val = get_master_clock_freq()/_dsp_impl->ddc_decim[which_dsp];
return;
default: UHD_THROW_PROP_GET_ERROR();
}
}
-void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){
+void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){
named_prop_t key = named_prop_t::extract(key_);
switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_STREAM_CMD:
+ issue_ddc_stream_cmd(val.as<stream_cmd_t>(), which_dsp);
+ return;
+
case DSP_PROP_FREQ_SHIFT:{
double new_freq = val.as<double>();
- _iface->poke32(_iface->regs.dsp_rx_freq,
+ _iface->poke32(_iface->regs.dsp_rx[which_dsp].freq,
dsp_type1::calc_cordic_word_and_update(new_freq, get_master_clock_freq())
);
- _ddc_freq = new_freq; //shadow
+ _dsp_impl->ddc_freq[which_dsp] = new_freq; //shadow
}
return;
case DSP_PROP_HOST_RATE:{
double extact_rate = get_master_clock_freq()/val.as<double>();
- _ddc_decim = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates);
+ _dsp_impl->ddc_decim[which_dsp] = pick_closest_rate(extact_rate, _dsp_impl->decim_and_interp_rates);
//set the decimation
- _iface->poke32(_iface->regs.dsp_rx_decim_rate, dsp_type1::calc_cic_filter_word(_ddc_decim));
+ _iface->poke32(_iface->regs.dsp_rx[which_dsp].decim_rate, dsp_type1::calc_cic_filter_word(_dsp_impl->ddc_decim[which_dsp]));
//set the scaling
static const boost::int16_t default_rx_scale_iq = 1024;
- _iface->poke32(_iface->regs.dsp_rx_scale_iq,
+ _iface->poke32(_iface->regs.dsp_rx[which_dsp].scale_iq,
dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq)
);
}
@@ -125,29 +193,14 @@ void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){
}
/***********************************************************************
- * DUC Helper Methods
- **********************************************************************/
-void usrp2_mboard_impl::init_duc_config(void){
- //create the duc in the tx dsp dict
- _tx_dsp_proxy = wax_obj_proxy::make(
- boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2),
- boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2)
- );
-
- //initial config and update
- duc_set(DSP_PROP_FREQ_SHIFT, double(0));
- duc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/default_interp));
-}
-
-/***********************************************************************
* DUC Properties
**********************************************************************/
-void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){
+void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){
named_prop_t key = named_prop_t::extract(key_);
switch(key.as<dsp_prop_t>()){
case DSP_PROP_NAME:
- val = _iface->get_cname() + " duc0";
+ val = str(boost::format("%s duc%d") % _iface->get_cname() % which_dsp);
return;
case DSP_PROP_OTHERS:
@@ -155,11 +208,7 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){
return;
case DSP_PROP_FREQ_SHIFT:
- val = _duc_freq;
- return;
-
- case DSP_PROP_FREQ_SHIFT_NAMES:
- val = prop_names_t(1, "");
+ val = _dsp_impl->duc_freq[which_dsp];
return;
case DSP_PROP_CODEC_RATE:
@@ -167,14 +216,14 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){
return;
case DSP_PROP_HOST_RATE:
- val = get_master_clock_freq()/_duc_interp;
+ val = get_master_clock_freq()/_dsp_impl->duc_interp[which_dsp];
return;
default: UHD_THROW_PROP_GET_ERROR();
}
}
-void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){
+void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){
named_prop_t key = named_prop_t::extract(key_);
switch(key.as<dsp_prop_t>()){
@@ -196,19 +245,19 @@ void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){
_iface->poke32(_iface->regs.dsp_tx_freq,
dsp_type1::calc_cordic_word_and_update(new_freq, codec_rate)
);
- _duc_freq = new_freq + dac_shift; //shadow
+ _dsp_impl->duc_freq[which_dsp] = new_freq + dac_shift; //shadow
}
return;
case DSP_PROP_HOST_RATE:{
double extact_rate = get_master_clock_freq()/val.as<double>();
- _duc_interp = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates);
+ _dsp_impl->duc_interp[which_dsp] = pick_closest_rate(extact_rate, _dsp_impl->decim_and_interp_rates);
//set the interpolation
- _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_duc_interp));
+ _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_dsp_impl->duc_interp[which_dsp]));
//set the scaling
- _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_duc_interp));
+ _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_dsp_impl->duc_interp[which_dsp]));
}
return;
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index a22f805e1..6eb047454 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -30,8 +30,8 @@ extern "C" {
#endif
//fpga and firmware compatibility numbers
-#define USRP2_FPGA_COMPAT_NUM 4
-#define USRP2_FW_COMPAT_NUM 8
+#define USRP2_FPGA_COMPAT_NUM 5
+#define USRP2_FW_COMPAT_NUM 9
//used to differentiate control packets over data port
#define USRP2_INVALID_VRT_HEADER 0
@@ -40,8 +40,9 @@ extern "C" {
// Dynamic and/or private ports: 49152-65535
#define USRP2_UDP_CTRL_PORT 49152
//#define USRP2_UDP_UPDATE_PORT 49154
-#define USRP2_UDP_DATA_PORT 49156
+#define USRP2_UDP_DSP0_PORT 49156
#define USRP2_UDP_ERR0_PORT 49157
+#define USRP2_UDP_DSP1_PORT 49158
////////////////////////////////////////////////////////////////////////
// I2C addresses
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index b20b6652e..b4f3e0873 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -18,6 +18,7 @@
#include "../../transport/vrt_packet_handler.hpp"
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
+#include <uhd/usrp/mboard_props.hpp>
#include <uhd/utils/byteswap.hpp>
#include <uhd/utils/thread_priority.hpp>
#include <uhd/transport/bounded_buffer.hpp>
@@ -119,27 +120,26 @@ private:
**********************************************************************/
struct usrp2_impl::io_impl{
- io_impl(size_t send_frame_size, const std::vector<zero_copy_if::sptr> &xports):
- xports(xports),
+ io_impl(std::vector<zero_copy_if::sptr> &dsp_xports):
+ dsp_xports(dsp_xports), //the assumption is that all data transports should be identical
get_recv_buffs_fcn(boost::bind(&usrp2_impl::io_impl::get_recv_buffs, this, _1)),
get_send_buffs_fcn(boost::bind(&usrp2_impl::io_impl::get_send_buffs, this, _1)),
- packet_handler_recv_state(xports.size()),
- packet_handler_send_state(xports.size()),
async_msg_fifo(100/*messages deep*/)
{
- for (size_t i = 0; i < xports.size(); i++){
- fc_mons.push_back(flow_control_monitor::sptr(
- new flow_control_monitor(usrp2_impl::sram_bytes/send_frame_size)
- ));
- //init empty packet infos
- vrt::if_packet_info_t packet_info;
- packet_info.packet_count = 0xf;
- packet_info.has_tsi = true;
- packet_info.tsi = 0;
- packet_info.has_tsf = true;
- packet_info.tsf = 0;
- prev_infos.push_back(packet_info);
+ for (size_t i = 0; i < dsp_xports.size(); i++){
+ fc_mons.push_back(flow_control_monitor::sptr(new flow_control_monitor(
+ usrp2_impl::sram_bytes/dsp_xports.front()->get_send_frame_size()
+ )));;
}
+
+ //init empty packet infos
+ vrt::if_packet_info_t packet_info = vrt::if_packet_info_t();
+ packet_info.packet_count = 0xf;
+ packet_info.has_tsi = true;
+ packet_info.tsi = 0;
+ packet_info.has_tsf = true;
+ packet_info.tsf = 0;
+ prev_infos.resize(dsp_xports.size(), packet_info);
}
~io_impl(void){
@@ -149,15 +149,15 @@ struct usrp2_impl::io_impl{
}
bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &buffs){
- UHD_ASSERT_THROW(xports.size() == buffs.size());
+ UHD_ASSERT_THROW(send_map.size() == buffs.size());
//calculate the flow control word
const boost::uint32_t fc_word32 = packet_handler_send_state.next_packet_seq;
//grab a managed buffer for each index
for (size_t i = 0; i < buffs.size(); i++){
- if (not fc_mons[i]->check_fc_condition(fc_word32, send_timeout)) return false;
- buffs[i] = xports[i]->get_send_buff(send_timeout);
+ if (not fc_mons[send_map[i]]->check_fc_condition(fc_word32, send_timeout)) return false;
+ buffs[i] = dsp_xports[send_map[i]]->get_send_buff(send_timeout);
if (not buffs[i].get()) return false;
buffs[i]->cast<boost::uint32_t *>()[0] = uhd::htonx(fc_word32);
}
@@ -166,7 +166,10 @@ struct usrp2_impl::io_impl{
bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs);
- const std::vector<zero_copy_if::sptr> &xports;
+ std::vector<zero_copy_if::sptr> &dsp_xports;
+
+ //mappings from channel index to dsp xport
+ std::vector<size_t> send_map, recv_map;
//timeouts set on calls to recv/send (passed into get buffs methods)
double recv_timeout, send_timeout;
@@ -186,7 +189,7 @@ struct usrp2_impl::io_impl{
vrt_packet_handler::send_state packet_handler_send_state;
//methods and variables for the pirate crew
- void recv_pirate_loop(zero_copy_if::sptr, usrp2_mboard_impl::sptr, size_t);
+ void recv_pirate_loop(usrp2_mboard_impl::sptr, zero_copy_if::sptr, size_t);
boost::thread_group recv_pirate_crew;
bool recv_pirate_crew_raiding;
bounded_buffer<async_metadata_t> async_msg_fifo;
@@ -200,17 +203,18 @@ struct usrp2_impl::io_impl{
* - put async message packets into queue
**********************************************************************/
void usrp2_impl::io_impl::recv_pirate_loop(
- zero_copy_if::sptr zc_if_err0,
- usrp2_mboard_impl::sptr mboard,
- size_t index
+ usrp2_mboard_impl::sptr mboard, zero_copy_if::sptr err_xport, size_t index
){
set_thread_priority_safe();
recv_pirate_crew_raiding = true;
spawn_mutex.unlock();
+ //store a reference to the flow control monitor (offset by max dsps)
+ flow_control_monitor &fc_mon = *(this->fc_mons[index*usrp2_mboard_impl::MAX_NUM_DSPS]);
+
while(recv_pirate_crew_raiding){
- managed_recv_buffer::sptr buff = zc_if_err0->get_recv_buff();
+ managed_recv_buffer::sptr buff = err_xport->get_recv_buff();
if (not buff.get()) continue; //ignore timeout/error buffers
try{
@@ -235,7 +239,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(
//catch the flow control packets and react
if (metadata.event_code == 0){
boost::uint32_t fc_word32 = (vrt_hdr + if_packet_info.num_header_words32)[1];
- this->fc_mons[index]->update_fc_condition(uhd::ntohx(fc_word32));
+ fc_mon.update_fc_condition(uhd::ntohx(fc_word32));
continue;
}
@@ -258,27 +262,52 @@ void usrp2_impl::io_impl::recv_pirate_loop(
**********************************************************************/
void usrp2_impl::io_init(void){
- //the assumption is that all data transports should be identical
- const size_t send_frame_size = _data_transports.front()->get_send_frame_size();
-
//create new io impl
- _io_impl = UHD_PIMPL_MAKE(io_impl, (send_frame_size, _data_transports));
+ _io_impl = UHD_PIMPL_MAKE(io_impl, (dsp_xports));
//create a new pirate thread for each zc if (yarr!!)
- for (size_t i = 0; i < _data_transports.size(); i++){
+ for (size_t i = 0; i < _mboards.size(); i++){
//lock the unlocked mutex (non-blocking)
_io_impl->spawn_mutex.lock();
//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(), _err0_transports.at(i),
- _mboards.at(i), i
+ _io_impl.get(), _mboards.at(i), err_xports.at(i), i
));
//block here until the spawned thread unlocks
_io_impl->spawn_mutex.lock();
//exit loop iteration in an unlocked condition
_io_impl->spawn_mutex.unlock();
}
+
+ //update mapping here since it didnt b4 when io init not called first
+ update_xport_channel_mapping();
+}
+
+void usrp2_impl::update_xport_channel_mapping(void){
+ if (_io_impl.get() == NULL) return; //not inited yet
+
+ _io_impl->recv_map.clear();
+ _io_impl->send_map.clear();
+
+ for (size_t i = 0; i < _mboards.size(); i++){
+
+ subdev_spec_t rx_subdev_spec = _mboards[i]->get_link()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>();
+ for (size_t j = 0; j < rx_subdev_spec.size(); j++){
+ _io_impl->recv_map.push_back(i*usrp2_mboard_impl::MAX_NUM_DSPS+j);
+ //std::cout << "recv_map.back() " << _io_impl->recv_map.back() << std::endl;
+ }
+
+ subdev_spec_t tx_subdev_spec = _mboards[i]->get_link()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>();
+ for (size_t j = 0; j < tx_subdev_spec.size(); j++){
+ _io_impl->send_map.push_back(i*usrp2_mboard_impl::MAX_NUM_DSPS+j);
+ //std::cout << "send_map.back() " << _io_impl->send_map.back() << std::endl;
+ }
+
+ }
+
+ _io_impl->packet_handler_recv_state = vrt_packet_handler::recv_state(_io_impl->recv_map.size());
+ _io_impl->packet_handler_send_state = vrt_packet_handler::send_state(_io_impl->send_map.size());
}
/***********************************************************************
@@ -300,7 +329,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 = _data_transports.front()->get_send_frame_size() - hdr_size;
+ const size_t bpp = dsp_xports.front()->get_send_frame_size() - hdr_size;
return bpp/_tx_otw_type.get_sample_size();
}
@@ -383,14 +412,15 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs(
vrt_packet_handler::managed_recv_buffs_t &buffs
){
if (buffs.size() == 1){
- buffs[0] = xports[0]->get_recv_buff(recv_timeout);
+ buffs[0] = dsp_xports[recv_map[0]]->get_recv_buff(recv_timeout);
if (buffs[0].get() == NULL) return false;
bool clear, msg; time_spec_t time; //unused variables
//call extract_packet_info to handle printing the overflows
- extract_packet_info(buffs[0], this->prev_infos[0], time, clear, msg);
+ extract_packet_info(buffs[0], this->prev_infos[recv_map[0]], time, clear, msg);
return true;
}
//-------------------- begin alignment logic ---------------------//
+ UHD_ASSERT_THROW(recv_map.size() == buffs.size());
boost::system_time exit_time = boost::get_system_time() + to_time_dur(recv_timeout);
managed_recv_buffer::sptr buff_tmp;
alignment_indexes indexes_to_do;
@@ -404,9 +434,9 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs(
//do an initial pop to load an initial sequence id
size_t index = indexes_to_do.front();
- buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time()));
+ buff_tmp = dsp_xports[recv_map[index]]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time()));
if (buff_tmp.get() == NULL) return false;
- extract_packet_info(buff_tmp, this->prev_infos[index], expected_time, clear, msg);
+ extract_packet_info(buff_tmp, this->prev_infos[recv_map[index]], expected_time, clear, msg);
if (clear) goto got_clear;
buffs[index] = buff_tmp;
if (msg) return handle_msg_packet(buffs, index);
@@ -417,10 +447,10 @@ UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs(
//pop an element off for this index
index = indexes_to_do.front();
- buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time()));
+ buff_tmp = dsp_xports[recv_map[index]]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time()));
if (buff_tmp.get() == NULL) return false;
time_spec_t this_time;
- extract_packet_info(buff_tmp, this->prev_infos[index], this_time, clear, msg);
+ extract_packet_info(buff_tmp, this->prev_infos[recv_map[index]], this_time, clear, msg);
if (clear) goto got_clear;
buffs[index] = buff_tmp;
if (msg) return handle_msg_packet(buffs, index);
@@ -458,13 +488,14 @@ 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 = _data_transports.front()->get_recv_frame_size() - hdr_size;
+ const size_t bpp = dsp_xports.front()->get_recv_frame_size() - hdr_size;
return bpp/_rx_otw_type.get_sample_size();
}
-static void handle_overflow(std::vector<usrp2_mboard_impl::sptr> &mboards, size_t chan){
+void usrp2_impl::handle_overflow(size_t chan){
std::cerr << "O" << std::flush;
- mboards.at(chan/mboards.size())->handle_overflow();
+ ldiv_t indexes = ldiv(chan, usrp2_mboard_impl::NUM_RX_DSPS);
+ _mboards.at(indexes.quot)->handle_overflow(indexes.rem);
}
size_t usrp2_impl::recv(
@@ -481,6 +512,6 @@ size_t usrp2_impl::recv(
_mboards.front()->get_master_clock_freq(), //master clock tick rate
uhd::transport::vrt::if_hdr_unpack_be,
_io_impl->get_recv_buffs_fcn,
- boost::bind(&handle_overflow, boost::ref(_mboards), _1)
+ boost::bind(&usrp2_impl::handle_overflow, this, _1)
);
}
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 397fae636..34a2b7c69 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -21,8 +21,8 @@
#include <uhd/usrp/misc_utils.hpp>
#include <uhd/usrp/dsp_utils.hpp>
#include <uhd/usrp/mboard_props.hpp>
-#include <uhd/utils/assert.hpp>
#include <uhd/utils/byteswap.hpp>
+#include <uhd/utils/assert.hpp>
#include <uhd/utils/algorithm.hpp>
#include <boost/bind.hpp>
#include <iostream>
@@ -33,35 +33,55 @@ static const size_t mimo_clock_sync_delay_cycles = 137;
using namespace uhd;
using namespace uhd::usrp;
+using namespace uhd::transport;
/***********************************************************************
- * Structors
+ * Helpers
**********************************************************************/
-usrp2_mboard_impl::usrp2_mboard_impl(
- size_t index,
- transport::udp_simple::sptr ctrl_transport,
- transport::zero_copy_if::sptr data_transport,
- transport::zero_copy_if::sptr err0_transport,
- const device_addr_t &device_args,
- size_t recv_samps_per_packet
-):
- _index(index),
- _iface(usrp2_iface::make(ctrl_transport))
-{
+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.
- transport::managed_send_buffer::sptr send_buff;
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))
};
- send_buff = data_transport->get_send_buff();
- std::memcpy(send_buff->cast<void*>(), &data, sizeof(data));
- send_buff->commit(sizeof(data));
- send_buff = err0_transport->get_send_buff();
+
+ 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_mboard_impl::usrp2_mboard_impl(
+ const device_addr_t &device_addr,
+ size_t index, usrp2_impl &device
+):
+ _index(index), _device(device),
+ _iface(usrp2_iface::make(udp_simple::make_connected(
+ device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT)
+ )))
+{
+ //construct transports for dsp and async errors
+ std::cout << "Making transport for DSP0..." << std::endl;
+ device.dsp_xports.push_back(udp_zero_copy::make(
+ device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_DSP0_PORT), device_addr
+ ));
+ init_xport(device.dsp_xports.back());
+
+ std::cout << "Making transport for DSP1..." << std::endl;
+ device.dsp_xports.push_back(udp_zero_copy::make(
+ device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_DSP1_PORT), device_addr
+ ));
+ init_xport(device.dsp_xports.back());
+
+ std::cout << "Making transport for ERR0..." << std::endl;
+ device.err_xports.push_back(udp_zero_copy::make(
+ device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_ERR0_PORT), device_addr_t()
+ ));
+ init_xport(device.err_xports.back());
//contruct the interfaces to mboard perifs
_clock_ctrl = usrp2_clock_ctrl::make(_iface);
@@ -72,66 +92,30 @@ usrp2_mboard_impl::usrp2_mboard_impl(
//if(_gps_ctrl->gps_detected()) std::cout << "GPS time: " << _gps_ctrl->get_time() << std::endl;
- //TODO move to dsp impl...
- //load the allowed decim/interp rates
- //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4)
- _allowed_decim_and_interp_rates.clear();
- for (size_t i = 4; i <= 128; i+=1){
- _allowed_decim_and_interp_rates.push_back(i);
- }
- for (size_t i = 130; i <= 256; i+=2){
- _allowed_decim_and_interp_rates.push_back(i);
- }
- for (size_t i = 260; i <= 512; i+=4){
- _allowed_decim_and_interp_rates.push_back(i);
- }
-
- //setup the vrt rx registers
- _iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //reset
- _iface->poke32(_iface->regs.rx_ctrl_nsamps_per_pkt, recv_samps_per_packet);
- _iface->poke32(_iface->regs.rx_ctrl_nchannels, 1);
- _iface->poke32(_iface->regs.rx_ctrl_vrt_header, 0
- | (0x1 << 28) //if data with stream id
- | (0x1 << 26) //has trailer
- | (0x3 << 22) //integer time other
- | (0x1 << 20) //fractional time sample count
- );
- _iface->poke32(_iface->regs.rx_ctrl_vrt_stream_id, usrp2_impl::RECV_SID);
- _iface->poke32(_iface->regs.rx_ctrl_vrt_trailer, 0);
- _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq()));
-
- //init the tx control registers
- _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset
- _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0); //1 channel
- _iface->poke32(_iface->regs.tx_ctrl_report_sid, usrp2_impl::ASYNC_SID);
- _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET);
+ //init the dsp stuff (before setting update packets)
+ dsp_init();
//setting the cycles per update (disabled by default)
- const double ups_per_sec = device_args.cast<double>("ups_per_sec", 0.0);
+ const double ups_per_sec = device_addr.cast<double>("ups_per_sec", 0.0);
if (ups_per_sec > 0.0){
const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec);
_iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up);
}
//setting the packets per update (enabled by default)
- const double ups_per_fifo = device_args.cast<double>("ups_per_fifo", 8.0);
+ size_t send_frame_size = device.dsp_xports[0]->get_send_frame_size();
+ const double ups_per_fifo = device_addr.cast<double>("ups_per_fifo", 8.0);
if (ups_per_fifo > 0.0){
- const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size());
+ const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/send_frame_size);
_iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up);
}
- //init the ddc
- init_ddc_config();
-
- //init the duc
- init_duc_config();
-
//initialize the clock configuration
- if (device_args.has_key("mimo_mode")){
- if (device_args["mimo_mode"] == "master"){
+ if (device_addr.has_key("mimo_mode")){
+ if (device_addr["mimo_mode"] == "master"){
_mimo_clocking_mode_is_master = true;
}
- else if (device_args["mimo_mode"] == "slave"){
+ else if (device_addr["mimo_mode"] == "slave"){
_mimo_clocking_mode_is_master = false;
}
else throw std::runtime_error(
@@ -158,13 +142,18 @@ usrp2_mboard_impl::usrp2_mboard_impl(
(*this)[MBOARD_PROP_RX_SUBDEV_SPEC] = subdev_spec_t();
(*this)[MBOARD_PROP_TX_SUBDEV_SPEC] = subdev_spec_t();
+ //------------------------------------------------------------------
//This is a hack/fix for the lingering packet problem.
stream_cmd_t stream_cmd(stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
- stream_cmd.num_samps = 1;
- this->issue_ddc_stream_cmd(stream_cmd);
- data_transport->get_recv_buff().get(); //recv with timeout for lingering
- data_transport->get_recv_buff().get(); //recv with timeout for expected
- _iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //resets sequence
+ for (size_t i = 0; i < NUM_RX_DSPS; i++){
+ size_t index = device.dsp_xports.size() - NUM_RX_DSPS + i;
+ stream_cmd.num_samps = 1;
+ this->issue_ddc_stream_cmd(stream_cmd, i);
+ device.dsp_xports.at(index)->get_recv_buff(0.01).get(); //recv with timeout for lingering
+ device.dsp_xports.at(index)->get_recv_buff(0.01).get(); //recv with timeout for expected
+ _iface->poke32(_iface->regs.rx_ctrl[i].clear_overrun, 1); //resets sequence
+ }
+ //------------------------------------------------------------------
}
usrp2_mboard_impl::~usrp2_mboard_impl(void){
@@ -265,19 +254,6 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){
_iface->poke32(_iface->regs.time64_secs, boost::uint32_t(time_spec.get_full_secs()));
}
-void usrp2_mboard_impl::handle_overflow(void){
- if (_continuous_streaming){ //re-issue the stream command if already continuous
- this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
- }
-}
-
-void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
- _continuous_streaming = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
- _iface->poke32(_iface->regs.rx_ctrl_stream_cmd, dsp_type1::calc_stream_cmd_word(stream_cmd));
- _iface->poke32(_iface->regs.rx_ctrl_time_secs, boost::uint32_t(stream_cmd.time_spec.get_full_secs()));
- _iface->poke32(_iface->regs.rx_ctrl_time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq()));
-}
-
/***********************************************************************
* MBoard Get Properties
**********************************************************************/
@@ -314,21 +290,19 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
return;
case MBOARD_PROP_RX_DSP:
- UHD_ASSERT_THROW(key.name == "");
- val = _rx_dsp_proxy->get_link();
+ val = _rx_dsp_proxies[key.name]->get_link();
return;
case MBOARD_PROP_RX_DSP_NAMES:
- val = prop_names_t(1, "");
+ val = _rx_dsp_proxies.keys();
return;
case MBOARD_PROP_TX_DSP:
- UHD_ASSERT_THROW(key.name == "");
- val = _tx_dsp_proxy->get_link();
+ val = _tx_dsp_proxies[key.name]->get_link();
return;
case MBOARD_PROP_TX_DSP_NAMES:
- val = prop_names_t(1, "");
+ val = _tx_dsp_proxies.keys();
return;
case MBOARD_PROP_CLOCK_CONFIG:
@@ -391,30 +365,32 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){
set_time_spec(val.as<time_spec_t>(), false);
return;
- case MBOARD_PROP_STREAM_CMD:
- issue_ddc_stream_cmd(val.as<stream_cmd_t>());
- return;
-
case MBOARD_PROP_RX_SUBDEV_SPEC:
_rx_subdev_spec = val.as<subdev_spec_t>();
verify_rx_subdev_spec(_rx_subdev_spec, this->get_link());
//sanity check
- UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1);
+ UHD_ASSERT_THROW(_rx_subdev_spec.size() <= NUM_RX_DSPS);
//set the mux
- _iface->poke32(_iface->regs.dsp_rx_mux, dsp_type1::calc_rx_mux_word(
- _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()
- ));
+ for (size_t i = 0; i < _rx_subdev_spec.size(); i++){
+ if (_rx_subdev_spec.size() >= 1) _iface->poke32(_iface->regs.dsp_rx[i].mux, dsp_type1::calc_rx_mux_word(
+ _dboard_manager->get_rx_subdev(_rx_subdev_spec[i].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()
+ ));
+ }
+ _device.update_xport_channel_mapping();
return;
case MBOARD_PROP_TX_SUBDEV_SPEC:
_tx_subdev_spec = val.as<subdev_spec_t>();
verify_tx_subdev_spec(_tx_subdev_spec, this->get_link());
//sanity check
- UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1);
+ UHD_ASSERT_THROW(_tx_subdev_spec.size() <= NUM_TX_DSPS);
//set the mux
- _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word(
- _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()
- ));
+ for (size_t i = 0; i < _rx_subdev_spec.size(); i++){
+ _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word(
+ _dboard_manager->get_tx_subdev(_tx_subdev_spec[i].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()
+ ));
+ }
+ _device.update_xport_channel_mapping();
return;
case MBOARD_PROP_EEPROM_MAP:
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 9ce0f7359..95031d211 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -22,14 +22,13 @@
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/warning.hpp>
-#include <boost/algorithm/string.hpp> //for split
+#include <uhd/utils/byteswap.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/regex.hpp>
#include <boost/bind.hpp>
-#include <boost/asio.hpp> //htonl and ntohl
+#include <boost/asio/ip/address_v4.hpp>
#include <iostream>
#include <vector>
@@ -39,66 +38,11 @@ using namespace uhd::transport;
namespace asio = boost::asio;
/***********************************************************************
- * Helper Functions
- **********************************************************************/
-template <class T> std::string num2str(T num){
- return boost::lexical_cast<std::string>(num);
-}
-
-//! separate indexed device addresses into a vector of device addresses
-device_addrs_t sep_indexed_dev_addrs(const device_addr_t &dev_addr){
- //------------ support old deprecated way and print warning --------
- if (dev_addr.has_key("addr") and not dev_addr["addr"].empty()){
- std::vector<std::string> addrs; boost::split(addrs, dev_addr["addr"], boost::is_any_of(" "));
- if (addrs.size() > 1){
- device_addr_t fixed_dev_addr = dev_addr;
- fixed_dev_addr.pop("addr");
- for (size_t i = 0; i < addrs.size(); i++){
- fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i];
- }
- uhd::warning::post(
- "addr = <space separated list of ip addresses> is deprecated.\n"
- "To address a multi-device, use multiple <key><index> = <val>.\n"
- "See the USRP-NXXX application notes. Two device example:\n"
- " addr0 = 192.168.10.2\n"
- " addr1 = 192.168.10.3\n"
- );
- return sep_indexed_dev_addrs(fixed_dev_addr);
- }
- }
- //------------------------------------------------------------------
- device_addrs_t dev_addrs;
- BOOST_FOREACH(const std::string &key, dev_addr.keys()){
- boost::cmatch matches;
- if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){
- throw std::runtime_error("unknown key format: " + key);
- }
- std::string key_part(matches[1].first, matches[1].second);
- std::string num_part(matches[2].first, matches[2].second);
- size_t num = (num_part.empty())? 0 : boost::lexical_cast<size_t>(num_part);
- dev_addrs.resize(std::max(num+1, dev_addrs.size()));
- dev_addrs[num][key_part] = dev_addr[key];
- }
- return dev_addrs;
-}
-
-//! combine a vector in device addresses into an indexed device address
-device_addr_t combine_dev_addr_vector(const device_addrs_t &dev_addrs){
- device_addr_t dev_addr;
- for (size_t i = 0; i < dev_addrs.size(); i++){
- BOOST_FOREACH(const std::string &key, dev_addrs[i].keys()){
- dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key];
- }
- }
- return dev_addr;
-}
-
-/***********************************************************************
* Discovery over the udp transport
**********************************************************************/
static device_addrs_t usrp2_find(const device_addr_t &hint_){
//handle the multi-device discovery
- device_addrs_t hints = sep_indexed_dev_addrs(hint_);
+ device_addrs_t hints = separate_device_addr(hint_);
if (hints.size() > 1){
device_addrs_t found_devices;
BOOST_FOREACH(const device_addr_t &hint_i, hints){
@@ -108,7 +52,7 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){
) % hint_i.to_string()));
found_devices.push_back(found_devices_i[0]);
}
- return device_addrs_t(1, combine_dev_addr_vector(found_devices));
+ return device_addrs_t(1, combine_device_addrs(found_devices));
}
//initialize the hint for a single device case
@@ -147,8 +91,8 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){
//send a hello control packet
usrp2_ctrl_data_t ctrl_data_out;
- ctrl_data_out.proto_ver = htonl(USRP2_FW_COMPAT_NUM);
- ctrl_data_out.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO);
+ ctrl_data_out.proto_ver = uhd::htonx<boost::uint32_t>(USRP2_FW_COMPAT_NUM);
+ ctrl_data_out.id = uhd::htonx<boost::uint32_t>(USRP2_CTRL_ID_WAZZUP_BRO);
udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out)));
//loop and recieve until the timeout
@@ -157,9 +101,9 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){
while(true){
size_t len = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem));
//std::cout << len << "\n";
- if (len > offsetof(usrp2_ctrl_data_t, data) and ntohl(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE){
+ if (len > offsetof(usrp2_ctrl_data_t, data) and uhd::ntohx(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE){
//make a boost asio ipv4 with the raw addr in host byte order
- boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.ip_addr));
+ boost::asio::ip::address_v4 ip_addr(uhd::ntohx(ctrl_data_in->data.ip_addr));
device_addr_t new_addr;
new_addr["type"] = "usrp2";
new_addr["addr"] = ip_addr.to_string();
@@ -167,9 +111,9 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){
//This operation can throw due to compatibility mismatch.
//In this case, the discovered device will be ignored.
try{
- mboard_eeprom_t mb_eeprom = usrp2_iface::make(
- udp_simple::make_connected(new_addr["addr"], num2str(USRP2_UDP_CTRL_PORT))
- )->mb_eeprom;
+ mboard_eeprom_t mb_eeprom = usrp2_iface::make(udp_simple::make_connected(
+ new_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT)
+ ))->mb_eeprom;
new_addr["name"] = mb_eeprom["name"];
new_addr["serial"] = mb_eeprom["serial"];
if (
@@ -197,40 +141,21 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){
/***********************************************************************
* Make
**********************************************************************/
-static device::sptr usrp2_make(const device_addr_t &device_addr){
+static device::sptr usrp2_make(const device_addr_t &_device_addr){
+ device_addr_t device_addr = _device_addr;
//setup the dsp transport hints (default to a large recv buff)
- device_addr_t dsp_xport_hints = device_addr;
- if (not dsp_xport_hints.has_key("recv_buff_size")){
- //only enable on platforms that are happy with the large buffer resize
- #if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)
+ if (not device_addr.has_key("recv_buff_size")){
+ #if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD)
+ //limit buffer resize on macos or it will error
+ device_addr["recv_buff_size"] = "1e6";
+ #elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)
//set to half-a-second of buffering at max rate
- dsp_xport_hints["recv_buff_size"] = "50e6";
- #endif /*defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)*/
- }
-
- //create a ctrl and data transport for each address
- std::vector<udp_simple::sptr> ctrl_transports;
- std::vector<zero_copy_if::sptr> data_transports;
- std::vector<zero_copy_if::sptr> err0_transports;
- const device_addrs_t device_addrs = sep_indexed_dev_addrs(device_addr);
-
- BOOST_FOREACH(const device_addr_t &dev_addr_i, device_addrs){
- ctrl_transports.push_back(udp_simple::make_connected(
- dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT)
- ));
- data_transports.push_back(udp_zero_copy::make(
- dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), dsp_xport_hints
- ));
- err0_transports.push_back(udp_zero_copy::make(
- dev_addr_i["addr"], num2str(USRP2_UDP_ERR0_PORT), device_addr_t()
- ));
+ device_addr["recv_buff_size"] = "50e6";
+ #endif
}
- //create the usrp2 implementation guts
- return device::sptr(new usrp2_impl(
- ctrl_transports, data_transports, err0_transports, device_addrs
- ));
+ return device::sptr(new usrp2_impl(device_addr));
}
UHD_STATIC_BLOCK(register_usrp2_device){
@@ -240,15 +165,9 @@ UHD_STATIC_BLOCK(register_usrp2_device){
/***********************************************************************
* Structors
**********************************************************************/
-usrp2_impl::usrp2_impl(
- std::vector<udp_simple::sptr> ctrl_transports,
- std::vector<zero_copy_if::sptr> data_transports,
- std::vector<zero_copy_if::sptr> err0_transports,
- const device_addrs_t &device_args
-):
- _data_transports(data_transports),
- _err0_transports(err0_transports)
-{
+usrp2_impl::usrp2_impl(const device_addr_t &device_addr){
+ device_addrs_t device_args = separate_device_addr(device_addr);
+
//setup rx otw type
_rx_otw_type.width = 16;
_rx_otw_type.shift = 0;
@@ -263,13 +182,16 @@ usrp2_impl::usrp2_impl(
//create a new mboard handler for each control transport
for(size_t i = 0; i < device_args.size(); i++){
- _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl(
- i, ctrl_transports[i], data_transports[i],
- err0_transports[i], device_args[i],
- this->get_max_recv_samps_per_packet()
- )));
+ device_addr_t dev_addr_i = device_args[i];
+ BOOST_FOREACH(const std::string &key, device_addr.keys()){
+ if (dev_addr_i.has_key(key)) continue;
+ dev_addr_i[key] = device_addr[key];
+ }
+ _mboards.push_back(usrp2_mboard_impl::sptr(
+ new usrp2_mboard_impl(dev_addr_i, i, *this)
+ ));
//use an empty name when there is only one mboard
- std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : "";
+ std::string name = (device_args.size() > 1)? boost::lexical_cast<std::string>(i) : "";
_mboard_dict[name] = _mboards.back();
}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 337f842d6..0676cecf2 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -71,6 +71,8 @@ private:
void set(const wax::obj &key, const wax::obj &val){return _set(key, val);}
};
+class usrp2_impl;
+
/*!
* USRP2 mboard implementation guts:
* The implementation details are encapsulated here.
@@ -80,14 +82,14 @@ class usrp2_mboard_impl : public wax::obj{
public:
typedef boost::shared_ptr<usrp2_mboard_impl> sptr;
+ static const size_t NUM_RX_DSPS = 2;
+ static const size_t NUM_TX_DSPS = 1;
+ static const size_t MAX_NUM_DSPS = 2;
+
//structors
usrp2_mboard_impl(
- size_t index,
- uhd::transport::udp_simple::sptr,
- uhd::transport::zero_copy_if::sptr,
- uhd::transport::zero_copy_if::sptr,
- const uhd::device_addr_t &device_args,
- size_t recv_samps_per_packet
+ const uhd::device_addr_t &device_addr,
+ size_t index, usrp2_impl &device
);
~usrp2_mboard_impl(void);
@@ -95,11 +97,11 @@ public:
return _clock_ctrl->get_master_clock_rate();
}
- void handle_overflow(void);
+ void handle_overflow(size_t);
private:
size_t _index;
- bool _continuous_streaming;
+ usrp2_impl &_device;
bool _mimo_clocking_mode_is_master;
//interfaces
@@ -147,27 +149,20 @@ private:
wax_obj_proxy::sptr _tx_dboard_proxy;
uhd::usrp::dboard_eeprom_t _tx_db_eeprom;
- //methods and shadows for the ddc dsp
- std::vector<size_t> _allowed_decim_and_interp_rates;
- size_t _ddc_decim;
- double _ddc_freq;
- void init_ddc_config(void);
- void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd);
-
- //methods and shadows for the duc dsp
- size_t _duc_interp;
- double _duc_freq;
- void init_duc_config(void);
+ //methods and shadows for the dsps
+ UHD_PIMPL_DECL(dsp_impl) _dsp_impl;
+ void dsp_init(void);
+ void issue_ddc_stream_cmd(const uhd::stream_cmd_t &, size_t);
//properties interface for ddc
- void ddc_get(const wax::obj &, wax::obj &);
- void ddc_set(const wax::obj &, const wax::obj &);
- wax_obj_proxy::sptr _rx_dsp_proxy;
+ void ddc_get(const wax::obj &, wax::obj &, size_t);
+ void ddc_set(const wax::obj &, const wax::obj &, size_t);
+ uhd::dict<std::string, wax_obj_proxy::sptr> _rx_dsp_proxies;
//properties interface for duc
- void duc_get(const wax::obj &, wax::obj &);
- void duc_set(const wax::obj &, const wax::obj &);
- wax_obj_proxy::sptr _tx_dsp_proxy;
+ void duc_get(const wax::obj &, wax::obj &, size_t);
+ void duc_set(const wax::obj &, const wax::obj &, size_t);
+ uhd::dict<std::string, wax_obj_proxy::sptr> _tx_dsp_proxies;
};
@@ -182,19 +177,7 @@ public:
static const boost::uint32_t RECV_SID = 1;
static const boost::uint32_t ASYNC_SID = 2;
- /*!
- * Create a new usrp2 impl base.
- * \param ctrl_transports the udp transports for control
- * \param data_transports the udp transports for data
- * \param err0_transports the udp transports for error
- * \param device_args optional misc device parameters
- */
- usrp2_impl(
- std::vector<uhd::transport::udp_simple::sptr> ctrl_transports,
- std::vector<uhd::transport::zero_copy_if::sptr> data_transports,
- std::vector<uhd::transport::zero_copy_if::sptr> err0_transports,
- const uhd::device_addrs_t &device_args
- );
+ usrp2_impl(const uhd::device_addr_t &);
~usrp2_impl(void);
@@ -213,6 +196,14 @@ public:
size_t get_max_recv_samps_per_packet(void) const;
bool recv_async_msg(uhd::async_metadata_t &, double);
+ void update_xport_channel_mapping(void);
+
+ //public frame sizes, set by mboard, used by io impl
+ size_t recv_frame_size, send_frame_size;
+
+ std::vector<uhd::transport::zero_copy_if::sptr> dsp_xports;
+ std::vector<uhd::transport::zero_copy_if::sptr> err_xports;
+
private:
//device properties interface
void get(const wax::obj &, wax::obj &);
@@ -223,11 +214,10 @@ private:
uhd::dict<std::string, usrp2_mboard_impl::sptr> _mboard_dict;
//io impl methods and members
- std::vector<uhd::transport::zero_copy_if::sptr> _data_transports;
- std::vector<uhd::transport::zero_copy_if::sptr> _err0_transports;
uhd::otw_type_t _rx_otw_type, _tx_otw_type;
UHD_PIMPL_DECL(io_impl) _io_impl;
void io_init(void);
+ void handle_overflow(size_t);
};
#endif /* INCLUDED_USRP2_IMPL_HPP */
diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp
index 84907c32e..66c3ac137 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.cpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.cpp
@@ -38,8 +38,10 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) {
x.sr_udp_sm = 96;
x.sr_tx_dsp = 208;
x.sr_tx_ctrl = 224;
- x.sr_rx_dsp = 160;
- x.sr_rx_ctrl = 176;
+ x.sr_rx_dsp0 = 160;
+ x.sr_rx_ctrl0 = 176;
+ x.sr_rx_dsp1 = 240;
+ x.sr_rx_ctrl1 = 32;
x.sr_time64 = 192;
x.sr_simtimer = 198;
x.sr_last = 255;
@@ -68,12 +70,18 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) {
x.dsp_tx_scale_iq = sr_addr(misc_output_base, x.sr_tx_dsp + 1);
x.dsp_tx_interp_rate = sr_addr(misc_output_base, x.sr_tx_dsp + 2);
x.dsp_tx_mux = sr_addr(misc_output_base, x.sr_tx_dsp + 4);
- x.dsp_rx_freq = sr_addr(misc_output_base, x.sr_rx_dsp + 0);
- x.dsp_rx_scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp + 1);
- x.dsp_rx_decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp + 2);
- x.dsp_rx_dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp + 3);
- x.dsp_rx_dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp + 4);
- x.dsp_rx_mux = sr_addr(misc_output_base, x.sr_rx_dsp + 5);
+ x.dsp_rx[0].freq = sr_addr(misc_output_base, x.sr_rx_dsp0 + 0);
+ x.dsp_rx[0].scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp0 + 1);
+ x.dsp_rx[0].decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp0 + 2);
+ x.dsp_rx[0].dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp0 + 3);
+ x.dsp_rx[0].dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp0 + 4);
+ x.dsp_rx[0].mux = sr_addr(misc_output_base, x.sr_rx_dsp0 + 5);
+ x.dsp_rx[1].freq = sr_addr(misc_output_base, x.sr_rx_dsp1 + 0);
+ x.dsp_rx[1].scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp1 + 1);
+ x.dsp_rx[1].decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp1 + 2);
+ x.dsp_rx[1].dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp1 + 3);
+ x.dsp_rx[1].dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp1 + 4);
+ x.dsp_rx[1].mux = sr_addr(misc_output_base, x.sr_rx_dsp1 + 5);
x.gpio_io = gpio_base + 0;
x.gpio_ddr = gpio_base + 4;
x.gpio_tx_sel = gpio_base + 8;
@@ -86,15 +94,24 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) {
x.atr_inrx_rxside = atr_base + 10;
x.atr_full_txside = atr_base + 12;
x.atr_full_rxside = atr_base + 14;
- x.rx_ctrl_stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl + 0);
- x.rx_ctrl_time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl + 1);
- x.rx_ctrl_time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl + 2);
- x.rx_ctrl_clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl + 3);
- x.rx_ctrl_vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl + 4);
- x.rx_ctrl_vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl + 5);
- x.rx_ctrl_vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl + 6);
- x.rx_ctrl_nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl + 7);
- x.rx_ctrl_nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl + 8);
+ x.rx_ctrl[0].stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 0);
+ x.rx_ctrl[0].time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 1);
+ x.rx_ctrl[0].time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 2);
+ x.rx_ctrl[0].clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 3);
+ x.rx_ctrl[0].vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 4);
+ x.rx_ctrl[0].vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 5);
+ x.rx_ctrl[0].vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 6);
+ x.rx_ctrl[0].nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 7);
+ x.rx_ctrl[0].nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl0 + 8);
+ x.rx_ctrl[1].stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 0);
+ x.rx_ctrl[1].time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 1);
+ x.rx_ctrl[1].time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 2);
+ x.rx_ctrl[1].clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 3);
+ x.rx_ctrl[1].vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 4);
+ x.rx_ctrl[1].vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 5);
+ x.rx_ctrl[1].vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 6);
+ x.rx_ctrl[1].nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 7);
+ x.rx_ctrl[1].nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl1 + 8);
x.tx_ctrl_num_chan = sr_addr(misc_output_base, x.sr_tx_ctrl + 0);
x.tx_ctrl_clear_state = sr_addr(misc_output_base, x.sr_tx_ctrl + 1);
x.tx_ctrl_report_sid = sr_addr(misc_output_base, x.sr_tx_ctrl + 2);
diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp
index 977b342cb..01f5ee65a 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.hpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.hpp
@@ -38,8 +38,10 @@ typedef struct {
int sr_udp_sm;
int sr_tx_dsp;
int sr_tx_ctrl;
- int sr_rx_dsp;
- int sr_rx_ctrl;
+ int sr_rx_dsp0;
+ int sr_rx_ctrl0;
+ int sr_rx_dsp1;
+ int sr_rx_ctrl1;
int sr_time64;
int sr_simtimer;
int sr_last;
@@ -68,12 +70,14 @@ typedef struct {
int dsp_tx_scale_iq;
int dsp_tx_interp_rate;
int dsp_tx_mux;
- int dsp_rx_freq;
- int dsp_rx_scale_iq;
- int dsp_rx_decim_rate;
- int dsp_rx_dcoffset_i;
- int dsp_rx_dcoffset_q;
- int dsp_rx_mux;
+ struct{
+ int freq;
+ int scale_iq;
+ int decim_rate;
+ int dcoffset_i;
+ int dcoffset_q;
+ int mux;
+ } dsp_rx[2];
int gpio_base;
int gpio_io;
int gpio_ddr;
@@ -88,15 +92,17 @@ typedef struct {
int atr_inrx_rxside;
int atr_full_txside;
int atr_full_rxside;
- int rx_ctrl_stream_cmd;
- int rx_ctrl_time_secs;
- int rx_ctrl_time_ticks;
- int rx_ctrl_clear_overrun;
- int rx_ctrl_vrt_header;
- int rx_ctrl_vrt_stream_id;
- int rx_ctrl_vrt_trailer;
- int rx_ctrl_nsamps_per_pkt;
- int rx_ctrl_nchannels;
+ struct{
+ int stream_cmd;
+ int time_secs;
+ int time_ticks;
+ int clear_overrun;
+ int vrt_header;
+ int vrt_stream_id;
+ int vrt_trailer;
+ int nsamps_per_pkt;
+ int nchannels;
+ } rx_ctrl[2];
int tx_ctrl_num_chan;
int tx_ctrl_clear_state;
int tx_ctrl_report_sid;
diff --git a/host/lib/usrp/usrp_e100/dsp_impl.cpp b/host/lib/usrp/usrp_e100/dsp_impl.cpp
index 7d358a607..8d084f066 100644
--- a/host/lib/usrp/usrp_e100/dsp_impl.cpp
+++ b/host/lib/usrp/usrp_e100/dsp_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -60,10 +60,6 @@ void usrp_e100_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){
val = _ddc_freq;
return;
- case DSP_PROP_FREQ_SHIFT_NAMES:
- val = prop_names_t(1, "");
- return;
-
case DSP_PROP_CODEC_RATE:
val = _clock_ctrl->get_fpga_clock_rate();
return;
@@ -84,6 +80,10 @@ void usrp_e100_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_STREAM_CMD:
+ issue_stream_cmd(val.as<stream_cmd_t>());
+ return;
+
case DSP_PROP_FREQ_SHIFT:{
double new_freq = val.as<double>();
_iface->poke32(UE_REG_DSP_RX_FREQ,
@@ -143,10 +143,6 @@ void usrp_e100_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){
val = _duc_freq;
return;
- case DSP_PROP_FREQ_SHIFT_NAMES:
- val = prop_names_t(1, "");
- return;
-
case DSP_PROP_CODEC_RATE:
val = _clock_ctrl->get_fpga_clock_rate();
return;
diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp
index 0e08cd435..a4db53715 100644
--- a/host/lib/usrp/usrp_e100/mboard_impl.cpp
+++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp
@@ -167,10 +167,6 @@ void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
- case MBOARD_PROP_STREAM_CMD:
- issue_stream_cmd(val.as<stream_cmd_t>());
- return;
-
case MBOARD_PROP_TIME_NOW:
case MBOARD_PROP_TIME_PPS:{
time_spec_t time_spec = val.as<time_spec_t>();
diff --git a/host/tests/tune_helper_test.cpp b/host/tests/tune_helper_test.cpp
index 735e7e948..aabaaaf6e 100644
--- a/host/tests/tune_helper_test.cpp
+++ b/host/tests/tune_helper_test.cpp
@@ -153,10 +153,6 @@ private:
val = _freq_shift;
return;
- case DSP_PROP_FREQ_SHIFT_NAMES:
- val = prop_names_t(1, "");
- return;
-
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -190,12 +186,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){
dummy_dsp dsp(100e6);
std::cout << "Testing tune helper RX automatic IF offset" << std::endl;
- tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9);
+ tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);
BOOST_CHECK_CLOSE(tr.actual_dsp_freq, -100e3, tolerance);
- double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0);
+ double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link());
BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance);
}
@@ -204,12 +200,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){
dummy_dsp dsp(100e6);
std::cout << "Testing tune helper TX automatic IF offset" << std::endl;
- tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9);
+ tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);
BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 100e3, tolerance);
- double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0);
+ double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link());
BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance);
}
@@ -218,12 +214,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){
dummy_dsp dsp(100e6);
std::cout << "Testing tune helper RX dummy basic board" << std::endl;
- tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 55e6);
+ tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 55e6);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 0.0, tolerance);
BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 45e6, tolerance);
- double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0);
+ double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link());
BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance);
}
@@ -235,21 +231,21 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){
std::cout << "Testing tune helper RX automatic LO offset B >> fs" << std::endl;
subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);
dsp[DSP_PROP_HOST_RATE] = double(4e6);
- tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+4e6/2, tolerance);
std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl;
subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);
dsp[DSP_PROP_HOST_RATE] = double(25e6);
- tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+(40e6-25e6)/2, tolerance);
std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl;
subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6);
dsp[DSP_PROP_HOST_RATE] = double(25e6);
- tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9, tolerance);
}