summaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-06-30 16:21:46 -0700
committerJosh Blum <josh@joshknows.com>2010-07-05 13:45:13 -0700
commit905f5b3b249a60401e181856ac6b3f2cae88d166 (patch)
tree1b1d859bc68f5e22f2c5cd035713510bb73ddd0a /host/lib/usrp
parenta38a0943490d10da733a529156a7650c056028e6 (diff)
downloaduhd-905f5b3b249a60401e181856ac6b3f2cae88d166.tar.gz
uhd-905f5b3b249a60401e181856ac6b3f2cae88d166.tar.bz2
uhd-905f5b3b249a60401e181856ac6b3f2cae88d166.zip
usrp2: split mboard impl into its own class, usrp2 device can instantiate N mboard impls for mimo setup (works with 1 for now)
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp18
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp20
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp113
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp78
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp102
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp175
6 files changed, 282 insertions, 224 deletions
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index fef486771..fa8d1a674 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -33,7 +33,7 @@ using namespace uhd::usrp;
/***********************************************************************
* Helper Methods
**********************************************************************/
-void usrp2_impl::dboard_init(void){
+void usrp2_mboard_impl::dboard_init(void){
//read the dboard eeprom to extract the dboard ids
_rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes()));
_tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes()));
@@ -46,12 +46,12 @@ void usrp2_impl::dboard_init(void){
//load dboards
_rx_dboard_proxy = wax_obj_proxy::make(
- boost::bind(&usrp2_impl::rx_dboard_get, this, _1, _2),
- boost::bind(&usrp2_impl::rx_dboard_set, this, _1, _2)
+ boost::bind(&usrp2_mboard_impl::rx_dboard_get, this, _1, _2),
+ boost::bind(&usrp2_mboard_impl::rx_dboard_set, this, _1, _2)
);
_tx_dboard_proxy = wax_obj_proxy::make(
- boost::bind(&usrp2_impl::tx_dboard_get, this, _1, _2),
- boost::bind(&usrp2_impl::tx_dboard_set, this, _1, _2)
+ boost::bind(&usrp2_mboard_impl::tx_dboard_get, this, _1, _2),
+ boost::bind(&usrp2_mboard_impl::tx_dboard_set, this, _1, _2)
);
//init the subdevs in use (use the first subdevice)
@@ -62,7 +62,7 @@ void usrp2_impl::dboard_init(void){
/***********************************************************************
* RX DBoard Properties
**********************************************************************/
-void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
+void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
@@ -96,7 +96,7 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
}
}
-void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){
+void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){
switch(key.as<dboard_prop_t>()){
case DBOARD_PROP_USED_SUBDEVS:{
_rx_subdevs_in_use = val.as<prop_names_t>();
@@ -122,7 +122,7 @@ void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){
/***********************************************************************
* TX DBoard Properties
**********************************************************************/
-void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
+void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
@@ -156,7 +156,7 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
}
}
-void usrp2_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){
+void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){
switch(key.as<dboard_prop_t>()){
case DBOARD_PROP_USED_SUBDEVS:{
_tx_subdevs_in_use = val.as<prop_names_t>();
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 367cde2e1..c315a2eec 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -41,11 +41,11 @@ pick_closest_rate(double exact_rate, const std::vector<rate_t> &rates){
return closest_match;
}
-void usrp2_impl::init_ddc_config(void){
+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_impl::ddc_get, this, _1, _2),
- boost::bind(&usrp2_impl::ddc_set, this, _1, _2)
+ boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2),
+ boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2)
);
//initial config and update
@@ -56,7 +56,7 @@ void usrp2_impl::init_ddc_config(void){
/***********************************************************************
* DDC Properties
**********************************************************************/
-void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
+void usrp2_mboard_impl::ddc_get(const wax::obj &key, wax::obj &val){
switch(key.as<dsp_prop_t>()){
case DSP_PROP_NAME:
val = std::string("usrp2 ddc0");
@@ -82,7 +82,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
}
}
-void usrp2_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){
switch(key.as<dsp_prop_t>()){
case DSP_PROP_FREQ_SHIFT:{
@@ -116,11 +116,11 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){
/***********************************************************************
* DUC Helper Methods
**********************************************************************/
-void usrp2_impl::init_duc_config(void){
+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_impl::duc_get, this, _1, _2),
- boost::bind(&usrp2_impl::duc_set, this, _1, _2)
+ boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2),
+ boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2)
);
//initial config and update
@@ -131,7 +131,7 @@ void usrp2_impl::init_duc_config(void){
/***********************************************************************
* DUC Properties
**********************************************************************/
-void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
+void usrp2_mboard_impl::duc_get(const wax::obj &key, wax::obj &val){
switch(key.as<dsp_prop_t>()){
case DSP_PROP_NAME:
val = std::string("usrp2 duc0");
@@ -157,7 +157,7 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
}
}
-void usrp2_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){
switch(key.as<dsp_prop_t>()){
case DSP_PROP_FREQ_SHIFT:{
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index e3a3a3b17..8b1864e2d 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -20,7 +20,7 @@
#include "usrp2_regs.hpp"
#include <uhd/utils/thread_priority.hpp>
#include <uhd/transport/convert_types.hpp>
-#include <uhd/transport/bounded_buffer.hpp>
+#include <uhd/transport/alignment_buffer.hpp>
#include <boost/format.hpp>
#include <boost/asio.hpp> //htonl and ntohl
#include <boost/bind.hpp>
@@ -36,54 +36,58 @@ namespace asio = boost::asio;
* io impl details (internal to this file)
**********************************************************************/
struct usrp2_impl::io_impl{
+ typedef alignment_buffer<managed_recv_buffer::sptr, time_spec_t> alignment_buffer_type;
- io_impl(zero_copy_if::sptr zc_if);
+ io_impl(std::vector<udp_zero_copy::sptr> &zc_ifs);
~io_impl(void);
- managed_recv_buffer::sptr get_recv_buff(void);
+ bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs);
//state management for the vrt packet handler code
vrt_packet_handler::recv_state packet_handler_recv_state;
vrt_packet_handler::send_state packet_handler_send_state;
//methods and variables for the recv pirate
- void recv_pirate_loop(zero_copy_if::sptr zc_if);
- boost::thread *recv_pirate_thread; bool recv_pirate_running;
- bounded_buffer<managed_recv_buffer::sptr>::sptr recv_pirate_booty;
+ void recv_pirate_loop(zero_copy_if::sptr zc_if, size_t index);
+ boost::thread_group recv_pirate_crew;
+ bool recv_pirate_crew_running;
+ alignment_buffer_type::sptr recv_pirate_booty;
};
-usrp2_impl::io_impl::io_impl(zero_copy_if::sptr zc_if): packet_handler_recv_state(1){
+usrp2_impl::io_impl::io_impl(std::vector<udp_zero_copy::sptr> &zc_ifs):
+ packet_handler_recv_state(zc_ifs.size())
+{
//create a large enough booty
- size_t num_frames = zc_if->get_num_recv_frames();
+ size_t num_frames = zc_ifs.at(0)->get_num_recv_frames();
std::cout << "Recv pirate num frames: " << num_frames << std::endl;
- recv_pirate_booty = bounded_buffer<managed_recv_buffer::sptr>::make(num_frames);
+ recv_pirate_booty = alignment_buffer_type::make(num_frames, zc_ifs.size());
- //create a new pirate thread (yarr!!)
- recv_pirate_thread = new boost::thread(
- boost::bind(&usrp2_impl::io_impl::recv_pirate_loop, this, zc_if)
- );
+ //create a new pirate thread for each zc if (yarr!!)
+ for (size_t i = 0; i < zc_ifs.size(); i++){
+ recv_pirate_crew.create_thread(
+ boost::bind(&usrp2_impl::io_impl::recv_pirate_loop, this, zc_ifs.at(i), i)
+ );
+ }
}
usrp2_impl::io_impl::~io_impl(void){
- recv_pirate_running = false;
- recv_pirate_thread->interrupt();
- recv_pirate_thread->join();
- delete recv_pirate_thread;
+ recv_pirate_crew_running = false;
+ recv_pirate_crew.interrupt_all();
+ recv_pirate_crew.join_all();
}
-managed_recv_buffer::sptr usrp2_impl::io_impl::get_recv_buff(void){
- managed_recv_buffer::sptr buff;
+bool usrp2_impl::io_impl::get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs){
boost::this_thread::disable_interruption di; //disable because the wait can throw
- recv_pirate_booty->pop_with_timed_wait(buff, boost::posix_time::milliseconds(100));
- return buff; //a timeout means that we return a null sptr...
+ return recv_pirate_booty->pop_elems_with_timed_wait(buffs, boost::posix_time::milliseconds(100));
}
-void usrp2_impl::io_impl::recv_pirate_loop(zero_copy_if::sptr zc_if){
+void usrp2_impl::io_impl::recv_pirate_loop(zero_copy_if::sptr zc_if, size_t index){
set_thread_priority_safe();
- recv_pirate_running = true;
- while(recv_pirate_running){
+ recv_pirate_crew_running = true;
+ while(recv_pirate_crew_running){
managed_recv_buffer::sptr buff = zc_if->get_recv_buff();
- if (buff->size()) recv_pirate_booty->push_with_pop_on_full(buff);
+ //TODO unpack vrt, get time spec, round to nearest packet bound, use below:
+ if (buff->size()) recv_pirate_booty->push_with_pop_on_full(buff, time_spec_t(/*todoseq*/), index);
}
}
@@ -102,54 +106,54 @@ void usrp2_impl::io_init(void){
_tx_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
//send a small data packet so the usrp2 knows the udp source port
- managed_send_buffer::sptr send_buff = _data_transport->get_send_buff();
- boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER);
- memcpy(send_buff->cast<void*>(), &data, sizeof(data));
- send_buff->commit(sizeof(data));
+ for(size_t i = 0; i < _data_transports.size(); i++){
+ managed_send_buffer::sptr send_buff = _data_transports[i]->get_send_buff();
+ boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER);
+ memcpy(send_buff->cast<void*>(), &data, sizeof(data));
+ send_buff->commit(sizeof(data));
+ }
- //setup RX DSP regs
- std::cout << "RX samples per packet: " << get_max_recv_samps_per_packet() << std::endl;
- _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, get_max_recv_samps_per_packet());
- _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1);
- _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset
- _iface->poke32(U2_REG_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(U2_REG_RX_CTRL_VRT_STREAM_ID, 0);
- _iface->poke32(U2_REG_RX_CTRL_VRT_TRAILER, 0);
+ //setup VRT RX DSP regs
+ for(size_t i = 0; i < _mboards.size(); i++){
+ _mboards[i]->setup_vrt_recv_regs(get_max_recv_samps_per_packet());
+ }
+ std::cout << "RX samples per packet: " << get_max_recv_samps_per_packet() << std::endl;
std::cout << "TX samples per packet: " << get_max_send_samps_per_packet() << std::endl;
//create new io impl
- _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport));
+ _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transports));
}
/***********************************************************************
* Send Data
**********************************************************************/
-bool tmp_todo_fixme_remove_get_send_buffs(vrt_packet_handler::managed_send_buffs_t &buffs, const zero_copy_if::sptr &zc_if){
- buffs[0] = zc_if->get_send_buff();
- return buffs[0].get() != NULL;
+bool get_send_buffs(
+ const std::vector<udp_zero_copy::sptr> &trans,
+ vrt_packet_handler::managed_send_buffs_t &buffs
+){
+ UHD_ASSERT_THROW(trans.size() == buffs.size());
+ for (size_t i = 0; i < buffs.size(); i++){
+ buffs[i] = trans[i]->get_send_buff();
+ }
+ return true;
}
size_t usrp2_impl::send(
const std::vector<const void *> &buffs,
- size_t nsamps_per_buff,
+ size_t num_samps,
const tx_metadata_t &metadata,
const io_type_t &io_type,
send_mode_t send_mode
){
return vrt_packet_handler::send(
_io_impl->packet_handler_send_state, //last state of the send handler
- buffs, nsamps_per_buff, //buffer to empty
+ buffs, num_samps, //buffer to fill
metadata, send_mode, //samples metadata
io_type, _tx_otw_type, //input and output types to convert
get_master_clock_freq(), //master clock tick rate
uhd::transport::vrt::if_hdr_pack_be,
- boost::bind(&tmp_todo_fixme_remove_get_send_buffs, _1, _data_transport),
+ boost::bind(&get_send_buffs, _data_transports, _1),
get_max_send_samps_per_packet()
);
}
@@ -157,25 +161,20 @@ size_t usrp2_impl::send(
/***********************************************************************
* Receive Data
**********************************************************************/
-bool tmp_todo_fixme_remove_get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, boost::shared_ptr<usrp2_impl::io_impl> impl){
- buffs[0] = impl->get_recv_buff();
- return buffs[0].get() != NULL;
-}
-
size_t usrp2_impl::recv(
const std::vector<void *> &buffs,
- size_t nsamps_per_buff,
+ size_t num_samps,
rx_metadata_t &metadata,
const io_type_t &io_type,
recv_mode_t recv_mode
){
return vrt_packet_handler::recv(
_io_impl->packet_handler_recv_state, //last state of the recv handler
- buffs, nsamps_per_buff, //buffer to empty
+ buffs, num_samps, //buffer to fill
metadata, recv_mode, //samples metadata
io_type, _rx_otw_type, //input and output types to convert
get_master_clock_freq(), //master clock tick rate
uhd::transport::vrt::if_hdr_unpack_be,
- boost::bind(&tmp_todo_fixme_remove_get_recv_buffs, _1, _io_impl)
+ boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl, _1)
);
}
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 2c900b328..903d5da86 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -30,16 +30,70 @@ using namespace uhd;
using namespace uhd::usrp;
/***********************************************************************
+ * Structors
+ **********************************************************************/
+usrp2_mboard_impl::usrp2_mboard_impl(
+ size_t index, transport::udp_simple::sptr ctrl_transport
+):
+ _index(index)
+{
+ //make a new interface for usrp2 stuff
+ _iface = usrp2_iface::make(ctrl_transport);
+ _clock_ctrl = usrp2_clock_ctrl::make(_iface);
+ _codec_ctrl = usrp2_codec_ctrl::make(_iface);
+ _serdes_ctrl = usrp2_serdes_ctrl::make(_iface);
+
+ //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);
+ }
+
+ //init the ddc
+ init_ddc_config();
+
+ //init the duc
+ init_duc_config();
+
+ //initialize the clock configuration
+ init_clock_config();
+
+ //init the tx and rx dboards (do last)
+ dboard_init();
+}
+
+usrp2_mboard_impl::~usrp2_mboard_impl(void){
+ /* NOP */
+}
+
+/***********************************************************************
* Helper Methods
**********************************************************************/
-void usrp2_impl::mboard_init(void){
- _mboard_proxy = wax_obj_proxy::make(
- boost::bind(&usrp2_impl::mboard_get, this, _1, _2),
- boost::bind(&usrp2_impl::mboard_set, this, _1, _2)
+void usrp2_mboard_impl::setup_vrt_recv_regs(size_t num_samps){
+ _max_recv_samps_per_packet = num_samps;
+
+ _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _max_recv_samps_per_packet);
+ _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1);
+ _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset
+ _iface->poke32(U2_REG_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(U2_REG_RX_CTRL_VRT_STREAM_ID, 0);
+ _iface->poke32(U2_REG_RX_CTRL_VRT_TRAILER, 0);
}
-void usrp2_impl::init_clock_config(void){
+void usrp2_mboard_impl::init_clock_config(void){
//setup the clock configuration settings
_clock_config.ref_source = clock_config_t::REF_INT;
_clock_config.pps_source = clock_config_t::PPS_SMA;
@@ -49,7 +103,7 @@ void usrp2_impl::init_clock_config(void){
update_clock_config();
}
-void usrp2_impl::update_clock_config(void){
+void usrp2_mboard_impl::update_clock_config(void){
boost::uint32_t pps_flags = 0;
//translate pps source enums
@@ -82,7 +136,7 @@ void usrp2_impl::update_clock_config(void){
_clock_ctrl->enable_external_ref(use_external);
}
-void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){
+void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){
//set the ticks
_iface->poke32(U2_REG_TIME64_TICKS, time_spec.get_tick_count(get_master_clock_freq()));
@@ -94,7 +148,7 @@ void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){
_iface->poke32(U2_REG_TIME64_SECS, boost::uint32_t(time_spec.get_full_secs()));
}
-void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
+void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
UHD_ASSERT_THROW(stream_cmd.num_samps <= U2_REG_RX_CTRL_MAX_SAMPS_PER_CMD);
//setup the mode to instruction flags
@@ -113,7 +167,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
//issue the stream command
_iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, U2_REG_RX_CTRL_MAKE_CMD(
- (inst_samps)? stream_cmd.num_samps : ((inst_chain)? get_max_recv_samps_per_packet() : 1),
+ (inst_samps)? stream_cmd.num_samps : ((inst_chain)? _max_recv_samps_per_packet : 1),
(stream_cmd.stream_now)? 1 : 0,
(inst_chain)? 1 : 0,
(inst_reload)? 1 : 0
@@ -125,7 +179,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
/***********************************************************************
* MBoard Get Properties
**********************************************************************/
-void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
+void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
@@ -148,7 +202,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
case MBOARD_PROP_NAME:
- val = std::string("usrp2 mboard");
+ val = str(boost::format("usrp2 mboard %d") % _index);
return;
case MBOARD_PROP_OTHERS:{
@@ -207,7 +261,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
/***********************************************************************
* MBoard Set Properties
**********************************************************************/
-void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
+void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){
//handle the other props
if (key.type() == typeid(std::string)){
if (key.as<std::string>() == "mac-addr"){
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 36c264c3c..af496bf69 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -21,6 +21,7 @@
#include <uhd/usrp/device_props.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
+#include <boost/algorithm/string.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
@@ -39,6 +40,15 @@ UHD_STATIC_BLOCK(register_usrp2_device){
}
/***********************************************************************
+ * Helper Functions
+ **********************************************************************/
+std::vector<std::string> split_addrs(const std::string &addrs_str){
+ std::vector<std::string> addrs;
+ boost::split(addrs, addrs_str, boost::is_any_of("\t "));
+ return addrs;
+}
+
+/***********************************************************************
* Discovery over the udp transport
**********************************************************************/
uhd::device_addrs_t usrp2::find(const device_addr_t &hint){
@@ -66,6 +76,16 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){
return usrp2_addrs;
}
+ //if there are multiple addresses, just return good, dont test
+ std::vector<std::string> addrs = split_addrs(hint["addr"]);
+ if (addrs.size() > 1){
+ device_addr_t new_addr;
+ new_addr["type"] = "usrp2";
+ new_addr["addr"] = hint["addr"];
+ usrp2_addrs.push_back(new_addr);
+ return usrp2_addrs;
+ }
+
//create a udp transport to communicate
std::string ctrl_port = boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT);
udp_simple::sptr udp_transport = udp_simple::make_broadcast(
@@ -112,11 +132,6 @@ template <class T> std::string num2str(T num){
}
device::sptr usrp2::make(const device_addr_t &device_addr){
- //create a control transport
- udp_simple::sptr ctrl_transport = udp_simple::make_connected(
- device_addr["addr"], num2str(USRP2_UDP_CTRL_PORT)
- );
-
//extract the receive and send buffer sizes
size_t recv_buff_size = 0, send_buff_size= 0 ;
if (device_addr.has_key("recv_buff_size")){
@@ -126,17 +141,23 @@ device::sptr usrp2::make(const device_addr_t &device_addr){
send_buff_size = size_t(boost::lexical_cast<double>(device_addr["send_buff_size"]));
}
- //create a data transport
- udp_zero_copy::sptr data_transport = udp_zero_copy::make(
- device_addr["addr"],
- num2str(USRP2_UDP_DATA_PORT),
- recv_buff_size,
- send_buff_size
- );
+ //create a ctrl and data transport for each address
+ std::vector<udp_simple::sptr> ctrl_transports;
+ std::vector<udp_zero_copy::sptr> data_transports;
+
+ BOOST_FOREACH(const std::string &addr, split_addrs(device_addr["addr"])){
+ ctrl_transports.push_back(udp_simple::make_connected(
+ addr, num2str(USRP2_UDP_CTRL_PORT)
+ ));
+ data_transports.push_back(udp_zero_copy::make(
+ addr, num2str(USRP2_UDP_DATA_PORT),
+ recv_buff_size, send_buff_size
+ ));
+ }
//create the usrp2 implementation guts
return device::sptr(
- new usrp2_impl(ctrl_transport, data_transport)
+ new usrp2_impl(ctrl_transports, data_transports)
);
}
@@ -144,44 +165,20 @@ device::sptr usrp2::make(const device_addr_t &device_addr){
* Structors
**********************************************************************/
usrp2_impl::usrp2_impl(
- udp_simple::sptr ctrl_transport,
- udp_zero_copy::sptr data_transport
-){
- _data_transport = data_transport;
-
- //make a new interface for usrp2 stuff
- _iface = usrp2_iface::make(ctrl_transport);
- _clock_ctrl = usrp2_clock_ctrl::make(_iface);
- _codec_ctrl = usrp2_codec_ctrl::make(_iface);
- _serdes_ctrl = usrp2_serdes_ctrl::make(_iface);
-
- //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);
+ std::vector<udp_simple::sptr> ctrl_transports,
+ std::vector<udp_zero_copy::sptr> data_transports
+):
+ _data_transports(data_transports)
+{
+ //create a new mboard handler for each control transport
+ for(size_t i = 0; i < ctrl_transports.size(); i++){
+ _mboards.push_back(usrp2_mboard_impl::sptr(
+ new usrp2_mboard_impl(i, ctrl_transports[i])
+ ));
+ //use an empty name when there is only one mboard
+ std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : "";
+ _mboard_dict[name] = _mboards.back();
}
- for (size_t i = 260; i <= 512; i+=4){
- _allowed_decim_and_interp_rates.push_back(i);
- }
-
- //init the mboard
- mboard_init();
-
- //init the ddc
- init_ddc_config();
-
- //init the duc
- init_duc_config();
-
- //initialize the clock configuration
- init_clock_config();
-
- //init the tx and rx dboards (do last)
- dboard_init();
//init the send and recv io
io_init();
@@ -206,12 +203,11 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){
return;
case DEVICE_PROP_MBOARD:
- UHD_ASSERT_THROW(name == "");
- val = _mboard_proxy->get_link();
+ val = _mboard_dict[name]->get_link();
return;
case DEVICE_PROP_MBOARD_NAMES:
- val = prop_names_t(1, "");
+ val = prop_names_t(_mboard_dict.keys());
return;
default: UHD_THROW_PROP_GET_ERROR();
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 70735173e..ccda5e3d8 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -62,102 +62,50 @@ public:
return sptr(new wax_obj_proxy(get, set));
}
- ~wax_obj_proxy(void){
- /* NOP */
- }
-
private:
- get_t _get;
- set_t _set;
-
- wax_obj_proxy(const get_t &get, const set_t &set){
- _get = get;
- _set = set;
- };
-
- void get(const wax::obj &key, wax::obj &val){
- return _get(key, val);
- }
-
- void set(const wax::obj &key, const wax::obj &val){
- return _set(key, val);
- }
+ get_t _get; set_t _set;
+ wax_obj_proxy(const get_t &get, const set_t &set): _get(get), _set(set){};
+ void get(const wax::obj &key, wax::obj &val){return _get(key, val);}
+ void set(const wax::obj &key, const wax::obj &val){return _set(key, val);}
};
/*!
- * USRP2 implementation guts:
+ * USRP2 mboard implementation guts:
* The implementation details are encapsulated here.
* Handles properties on the mboard, dboard, dsps...
*/
-class usrp2_impl : public uhd::device{
+class usrp2_mboard_impl : public wax::obj{
public:
- /*!
- * Create a new usrp2 impl base.
- * \param ctrl_transport the udp transport for control
- * \param data_transport the udp transport for data
- */
- usrp2_impl(
- uhd::transport::udp_simple::sptr ctrl_transport,
- uhd::transport::udp_zero_copy::sptr data_transport
- );
+ typedef boost::shared_ptr<usrp2_mboard_impl> sptr;
- ~usrp2_impl(void);
+ //structors
+ usrp2_mboard_impl(size_t index, uhd::transport::udp_simple::sptr);
+ ~usrp2_mboard_impl(void);
- //the io interface
- size_t get_max_send_samps_per_packet(void) const{
- return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size();
- }
- size_t send(
- const std::vector<const void *> &, size_t,
- const uhd::tx_metadata_t &,
- const uhd::io_type_t &,
- uhd::device::send_mode_t
- );
- size_t get_max_recv_samps_per_packet(void) const{
- return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size();
- }
- size_t recv(
- const std::vector<void *> &, size_t,
- uhd::rx_metadata_t &,
- const uhd::io_type_t &,
- uhd::device::recv_mode_t
- );
-
- UHD_PIMPL_DECL(io_impl) _io_impl;
+ void setup_vrt_recv_regs(size_t num_samps);
-private:
inline double get_master_clock_freq(void){
return _clock_ctrl->get_master_clock_rate();
}
- //device properties interface
+ //properties for this mboard
void get(const wax::obj &, wax::obj &);
void set(const wax::obj &, const wax::obj &);
+private:
+ size_t _index;
+ size_t _max_recv_samps_per_packet;
+
//interfaces
usrp2_iface::sptr _iface;
usrp2_clock_ctrl::sptr _clock_ctrl;
usrp2_codec_ctrl::sptr _codec_ctrl;
usrp2_serdes_ctrl::sptr _serdes_ctrl;
- /*******************************************************************
- * Deal with the rx and tx packet sizes
- ******************************************************************/
- static const size_t _max_rx_bytes_per_packet =
- USRP2_UDP_BYTES -
- USRP2_HOST_RX_VRT_HEADER_WORDS32*sizeof(boost::uint32_t) -
- USRP2_HOST_RX_VRT_TRAILER_WORDS32*sizeof(boost::uint32_t)
- ;
- static const size_t _max_tx_bytes_per_packet =
- USRP2_UDP_BYTES -
- uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
- ;
-
- uhd::otw_type_t _rx_otw_type, _tx_otw_type;
- void io_init(void);
-
- //udp transports for control and data
- uhd::transport::udp_zero_copy::sptr _data_transport;
+ //rx and tx dboard methods and objects
+ uhd::usrp::dboard_manager::sptr _dboard_manager;
+ uhd::usrp::dboard_iface::sptr _dboard_iface;
+ void dboard_init(void);
//methods and shadows for clock configuration
uhd::clock_config_t _clock_config;
@@ -165,17 +113,6 @@ private:
void update_clock_config(void);
void set_time_spec(const uhd::time_spec_t &time_spec, bool now);
- //rx and tx dboard methods and objects
- uhd::usrp::dboard_manager::sptr _dboard_manager;
- uhd::usrp::dboard_iface::sptr _dboard_iface;
- void dboard_init(void);
-
- //properties for the mboard
- void mboard_init(void);
- void mboard_get(const wax::obj &, wax::obj &);
- void mboard_set(const wax::obj &, const wax::obj &);
- wax_obj_proxy::sptr _mboard_proxy;
-
//properties interface for rx dboard
void rx_dboard_get(const wax::obj &, wax::obj &);
void rx_dboard_set(const wax::obj &, const wax::obj &);
@@ -214,4 +151,76 @@ private:
};
+/*!
+ * USRP2 implementation guts:
+ * The implementation details are encapsulated here.
+ * Handles device properties and streaming...
+ */
+class usrp2_impl : public uhd::device{
+public:
+ /*!
+ * Create a new usrp2 impl base.
+ * \param ctrl_transports the udp transports for control
+ * \param data_transports the udp transports for data
+ */
+ usrp2_impl(
+ std::vector<uhd::transport::udp_simple::sptr> ctrl_transports,
+ std::vector<uhd::transport::udp_zero_copy::sptr> data_transports
+ );
+
+ ~usrp2_impl(void);
+
+ //the io interface
+ size_t get_max_send_samps_per_packet(void) const{
+ return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size();
+ }
+ size_t send(
+ const std::vector<const void *> &, size_t,
+ const uhd::tx_metadata_t &,
+ const uhd::io_type_t &,
+ uhd::device::send_mode_t
+ );
+ size_t get_max_recv_samps_per_packet(void) const{
+ return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size();
+ }
+ size_t recv(
+ const std::vector<void *> &, size_t,
+ uhd::rx_metadata_t &,
+ const uhd::io_type_t &,
+ uhd::device::recv_mode_t
+ );
+
+private:
+ inline double get_master_clock_freq(void){
+ return _mboards.front()->get_master_clock_freq();
+ }
+
+ //device properties interface
+ void get(const wax::obj &, wax::obj &);
+ void set(const wax::obj &, const wax::obj &);
+
+ //pointers to mboards on this device (think mimo setup)
+ std::vector<usrp2_mboard_impl::sptr> _mboards;
+ uhd::dict<std::string, usrp2_mboard_impl::sptr> _mboard_dict;
+
+ /*******************************************************************
+ * Deal with the rx and tx packet sizes
+ ******************************************************************/
+ static const size_t _max_rx_bytes_per_packet =
+ USRP2_UDP_BYTES -
+ USRP2_HOST_RX_VRT_HEADER_WORDS32*sizeof(boost::uint32_t) -
+ USRP2_HOST_RX_VRT_TRAILER_WORDS32*sizeof(boost::uint32_t)
+ ;
+ static const size_t _max_tx_bytes_per_packet =
+ USRP2_UDP_BYTES -
+ uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) -
+ sizeof(uhd::transport::vrt::if_packet_info_t::cid) //no class id ever used
+ ;
+
+ std::vector<uhd::transport::udp_zero_copy::sptr> _data_transports;
+ uhd::otw_type_t _rx_otw_type, _tx_otw_type;
+ UHD_PIMPL_DECL(io_impl) _io_impl;
+ void io_init(void);
+};
+
#endif /* INCLUDED_USRP2_IMPL_HPP */