aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/usrp2
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/usrp2')
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp1
-rw-r--r--host/lib/usrp/usrp2/dboard_interface.cpp99
-rw-r--r--host/lib/usrp/usrp2/fw_common.h7
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp153
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp8
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp32
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp13
7 files changed, 128 insertions, 185 deletions
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index d1515f2d5..3ac805421 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -22,6 +22,7 @@
#include <uhd/usrp/dboard_props.hpp>
#include <uhd/utils/assert.hpp>
#include <boost/format.hpp>
+#include <iostream>
using namespace uhd;
using namespace uhd::usrp;
diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp
index 6dd756420..d10cfa37e 100644
--- a/host/lib/usrp/usrp2/dboard_interface.cpp
+++ b/host/lib/usrp/usrp2/dboard_interface.cpp
@@ -42,11 +42,21 @@ public:
double get_rx_clock_rate(void);
double get_tx_clock_rate(void);
-private:
- byte_vector_t transact_spi(
- spi_dev_t, spi_edge_t, const byte_vector_t &, bool
+ void write_spi(
+ unit_type_t unit,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits
+ );
+
+ boost::uint32_t read_write_spi(
+ unit_type_t unit,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits
);
+private:
usrp2_impl *_impl;
boost::uint32_t _ddr_shadow;
};
@@ -136,62 +146,35 @@ void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost:
* SPI
**********************************************************************/
/*!
- * Static function to convert a spi dev enum
- * to an over-the-wire value for the usrp2 control.
- * \param dev the dboard interface spi dev enum
+ * Static function to convert a unit type enum
+ * to an over-the-wire value for the spi device.
+ * \param unit the dboard interface unit type enum
* \return an over the wire representation
*/
-static boost::uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){
- switch(dev){
- case uhd::usrp::dboard_interface::SPI_DEV_TX: return SPI_SS_TX_DB;
- case uhd::usrp::dboard_interface::SPI_DEV_RX: return SPI_SS_RX_DB;
+static boost::uint8_t unit_to_otw_dev(dboard_interface::unit_type_t unit){
+ switch(unit){
+ case dboard_interface::UNIT_TYPE_TX: return SPI_SS_TX_DB;
+ case dboard_interface::UNIT_TYPE_RX: return SPI_SS_RX_DB;
}
- throw std::invalid_argument("unknown spi device type");
+ throw std::invalid_argument("unknown unit type type");
}
-/*!
- * Static function to convert a spi edge enum
- * to an over-the-wire value for the usrp2 control.
- * \param edge the dboard interface spi edge enum
- * \return an over the wire representation
- */
-static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_edge_t edge){
- switch(edge){
- case uhd::usrp::dboard_interface::SPI_EDGE_RISE: return USRP2_CLK_EDGE_RISE;
- case uhd::usrp::dboard_interface::SPI_EDGE_FALL: return USRP2_CLK_EDGE_FALL;
- }
- throw std::invalid_argument("unknown spi edge type");
+void usrp2_dboard_interface::write_spi(
+ unit_type_t unit,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits
+){
+ _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, false /*no rb*/);
}
-dboard_interface::byte_vector_t usrp2_dboard_interface::transact_spi(
- spi_dev_t dev,
- spi_edge_t edge,
- const byte_vector_t &buf,
- bool readback
+boost::uint32_t usrp2_dboard_interface::read_write_spi(
+ unit_type_t unit,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits
){
- //setup the out data
- usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO);
- out_data.data.spi_args.dev = spi_dev_to_otw(dev);
- out_data.data.spi_args.edge = spi_edge_to_otw(edge);
- out_data.data.spi_args.readback = (readback)? 1 : 0;
- out_data.data.spi_args.bytes = buf.size();
-
- //limitation of spi transaction size
- ASSERT_THROW(buf.size() <= sizeof(out_data.data.spi_args.data));
-
- //copy in the data
- std::copy(buf.begin(), buf.end(), out_data.data.spi_args.data);
-
- //send and recv
- usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data);
- ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE);
- ASSERT_THROW(in_data.data.spi_args.bytes == buf.size());
-
- //copy out the data
- byte_vector_t result(buf.size());
- std::copy(in_data.data.spi_args.data, in_data.data.spi_args.data + buf.size(), result.begin());
- return result;
+ return _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, true /*rb*/);
}
/***********************************************************************
@@ -245,19 +228,19 @@ dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, s
* \param unit the dboard interface unit type enum
* \return an over the wire representation
*/
-static boost::uint8_t spi_dev_to_otw(dboard_interface::unit_type_t unit){
+static boost::uint8_t unit_to_otw(dboard_interface::unit_type_t unit){
switch(unit){
- case uhd::usrp::dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX;
- case uhd::usrp::dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX;
+ case dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX;
+ case dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX;
}
throw std::invalid_argument("unknown unit type type");
}
-void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, int which, int value){
+void usrp2_dboard_interface::write_aux_dac(unit_type_t unit, int which, int value){
//setup the out data
usrp2_ctrl_data_t out_data;
out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO);
- out_data.data.aux_args.dir = spi_dev_to_otw(unit);
+ out_data.data.aux_args.dir = unit_to_otw(unit);
out_data.data.aux_args.which = which;
out_data.data.aux_args.value = htonl(value);
@@ -266,11 +249,11 @@ void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, i
ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE);
}
-int usrp2_dboard_interface::read_aux_adc(dboard_interface::unit_type_t unit, int which){
+int usrp2_dboard_interface::read_aux_adc(unit_type_t unit, int which){
//setup the out data
usrp2_ctrl_data_t out_data;
out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO);
- out_data.data.aux_args.dir = spi_dev_to_otw(unit);
+ out_data.data.aux_args.dir = unit_to_otw(unit);
out_data.data.aux_args.which = which;
//send and recv
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 019f3b931..b600a2a70 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -110,10 +110,11 @@ typedef struct{
} dboard_ids;
struct {
_SINS_ uint8_t dev;
- _SINS_ uint8_t edge;
+ _SINS_ uint8_t miso_edge;
+ _SINS_ uint8_t mosi_edge;
_SINS_ uint8_t readback;
- _SINS_ uint8_t bytes;
- _SINS_ uint8_t data[sizeof(_SINS_ uint32_t)];
+ _SINS_ uint32_t data;
+ _SINS_ uint8_t num_bits;
} spi_args;
struct {
_SINS_ uint8_t addr;
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index a58e32619..a760cbe3d 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -15,9 +15,11 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <complex>
-#include <boost/format.hpp>
#include "usrp2_impl.hpp"
+#include <uhd/transport/convert_types.hpp>
+#include <boost/format.hpp>
+#include <complex>
+#include <iostream>
using namespace uhd;
using namespace uhd::usrp;
@@ -25,101 +27,26 @@ using namespace uhd::transport;
namespace asio = boost::asio;
/***********************************************************************
- * Constants
- **********************************************************************/
-typedef std::complex<float> fc32_t;
-typedef std::complex<boost::int16_t> sc16_t;
-
-static const float shorts_per_float = float(1 << 15);
-static const float floats_per_short = float(1.0/shorts_per_float);
-
-/***********************************************************************
* Helper Functions
**********************************************************************/
void usrp2_impl::io_init(void){
+ //setup otw type
+ _otw_type.width = 16;
+ _otw_type.shift = 0;
+ _otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
+
//initially empty copy buffer
_rx_copy_buff = asio::buffer("", 0);
//send a small data packet so the usrp2 knows the udp source port
//and the maximum number of lines (32 bit words) per packet
+ managed_send_buffer::sptr send_buff = _data_transport->get_send_buff();
boost::uint32_t data[2] = {
htonl(USRP2_INVALID_VRT_HEADER),
htonl(_max_rx_samples_per_packet)
};
- _data_transport->send(asio::buffer(&data, sizeof(data)));
-}
-
-#define unrolled_loop(__inst, __len){ \
- size_t __i = 0; \
- for(; __i < (__len & ~0x3); __i+= 4){ \
- __inst(__i+0); __inst(__i+1); \
- __inst(__i+2); __inst(__i+3); \
- } \
- for(; __i < __len; __i++){ \
- __inst(__i); \
- } \
-}
-
-// set a boolean flag that indicates the endianess
-#ifdef HAVE_BIG_ENDIAN
-static const bool is_big_endian = true;
-#else
-static const bool is_big_endian = false;
-#endif
-
-static inline void host_floats_to_usrp2_items(
- boost::uint32_t *usrp2_items,
- const fc32_t *host_floats,
- size_t num_samps
-){
- #define host_floats_to_usrp2_items_i(i){ \
- boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); \
- boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); \
- usrp2_items[i] = htonl((real << 16) | (imag << 0)); \
- }
- unrolled_loop(host_floats_to_usrp2_items_i, num_samps);
-}
-
-static inline void usrp2_items_to_host_floats(
- fc32_t *host_floats,
- const boost::uint32_t *usrp2_items,
- size_t num_samps
-){
- #define usrp2_items_to_host_floats_i(i){ \
- boost::uint32_t item = ntohl(usrp2_items[i]); \
- boost::int16_t real = boost::uint16_t(item >> 16); \
- boost::int16_t imag = boost::uint16_t(item >> 0); \
- host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); \
- }
- unrolled_loop(usrp2_items_to_host_floats_i, num_samps);
-}
-
-static inline void host_items_to_usrp2_items(
- boost::uint32_t *usrp2_items,
- const boost::uint32_t *host_items,
- size_t num_samps
-){
- #define host_items_to_usrp2_items_i(i) usrp2_items[i] = htonl(host_items[i])
- if (is_big_endian){
- std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t));
- }
- else{
- unrolled_loop(host_items_to_usrp2_items_i, num_samps);
- }
-}
-
-static inline void usrp2_items_to_host_items(
- boost::uint32_t *host_items,
- const boost::uint32_t *usrp2_items,
- size_t num_samps
-){
- #define usrp2_items_to_host_items_i(i) host_items[i] = ntohl(usrp2_items[i])
- if (is_big_endian){
- std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t));
- }
- else{
- unrolled_loop(usrp2_items_to_host_items_i, num_samps);
- }
+ memcpy(send_buff->cast<void*>(), data, sizeof(data));
+ send_buff->done(sizeof(data));
}
/***********************************************************************
@@ -127,15 +54,15 @@ static inline void usrp2_items_to_host_items(
**********************************************************************/
void usrp2_impl::recv_raw(rx_metadata_t &metadata){
//do a receive
- _rx_smart_buff = _data_transport->recv();
+ _rx_smart_buff = _data_transport->get_recv_buff();
//unpack the vrt header
- size_t num_packet_words32 = asio::buffer_size(_rx_smart_buff->get())/sizeof(boost::uint32_t);
+ size_t num_packet_words32 = _rx_smart_buff->size()/sizeof(boost::uint32_t);
if (num_packet_words32 == 0){
_rx_copy_buff = boost::asio::buffer("", 0);
return; //must exit here after setting the buffer
}
- const boost::uint32_t *vrt_hdr = asio::buffer_cast<const boost::uint32_t *>(_rx_smart_buff->get());
+ const boost::uint32_t *vrt_hdr = _rx_smart_buff->cast<const boost::uint32_t *>();
size_t num_header_words32_out, num_payload_words32_out, packet_count_out;
try{
vrt::unpack(
@@ -144,7 +71,8 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){
num_header_words32_out, //output
num_payload_words32_out, //output
num_packet_words32, //input
- packet_count_out //output
+ packet_count_out, //output
+ get_master_clock_freq()
);
}catch(const std::exception &e){
std::cerr << "bad vrt header: " << e.what() << std::endl;
@@ -176,10 +104,12 @@ size_t usrp2_impl::send(
){
tx_metadata_t metadata = metadata_; //rw copy to change later
- boost::uint32_t tx_mem[_mtu/sizeof(boost::uint32_t)];
- size_t num_samps = std::min(
+ transport::managed_send_buffer::sptr send_buff = _data_transport->get_send_buff();
+ boost::uint32_t *tx_mem = send_buff->cast<boost::uint32_t *>();
+ size_t num_samps = std::min(std::min(
asio::buffer_size(buff)/io_type.size,
- size_t(_max_tx_samples_per_packet)
+ size_t(_max_tx_samples_per_packet)),
+ send_buff->size()/io_type.size
);
//kill the end of burst flag if this is a fragment
@@ -196,25 +126,21 @@ size_t usrp2_impl::send(
num_header_words32, //output
num_samps, //input
num_packet_words32, //output
- packet_count //input
+ packet_count, //input
+ get_master_clock_freq()
);
boost::uint32_t *items = tx_mem + num_header_words32; //offset for data
- //copy the samples into the send buffer
- switch(io_type.tid){
- case io_type_t::COMPLEX_FLOAT32:
- host_floats_to_usrp2_items(items, asio::buffer_cast<const fc32_t*>(buff), num_samps);
- break;
- case io_type_t::COMPLEX_INT16:
- host_items_to_usrp2_items(items, asio::buffer_cast<const boost::uint32_t*>(buff), num_samps);
- break;
- default:
- throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%c\"") % io_type.tid));
- }
+ //copy-convert the samples into the send buffer
+ convert_io_type_to_otw_type(
+ asio::buffer_cast<const void*>(buff), io_type,
+ (void*)items, _otw_type,
+ num_samps
+ );
//send and return number of samples
- _data_transport->send(asio::buffer(tx_mem, num_packet_words32*sizeof(boost::uint32_t)));
+ send_buff->done(num_packet_words32*sizeof(boost::uint32_t));
return num_samps;
}
@@ -251,17 +177,12 @@ size_t usrp2_impl::recv(
metadata.fragment_offset = _fragment_offset_in_samps;
_fragment_offset_in_samps += num_samps; //set for next time
- //copy the samples from the recv buffer
- switch(io_type.tid){
- case io_type_t::COMPLEX_FLOAT32:
- usrp2_items_to_host_floats(asio::buffer_cast<fc32_t*>(buff), items, num_samps);
- break;
- case io_type_t::COMPLEX_INT16:
- usrp2_items_to_host_items(asio::buffer_cast<boost::uint32_t*>(buff), items, num_samps);
- break;
- default:
- throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%c\"") % io_type.tid));
- }
+ //copy-convert the samples from the recv buffer
+ convert_otw_type_to_io_type(
+ (const void*)items, _otw_type,
+ asio::buffer_cast<void*>(buff), io_type,
+ num_samps
+ );
//update the rx copy buffer to reflect the bytes copied
_rx_copy_buff = asio::buffer(
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 94ab88a6b..2fa2e5211 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -33,10 +33,6 @@ void usrp2_impl::mboard_init(void){
boost::bind(&usrp2_impl::mboard_get, this, _1, _2),
boost::bind(&usrp2_impl::mboard_set, this, _1, _2)
);
-
- //set the time on the usrp2 as close as possible to the system utc time
- boost::posix_time::ptime now(boost::posix_time::microsec_clock::universal_time());
- set_time_spec(time_spec_t(now, get_master_clock_freq()), true);
}
void usrp2_impl::init_clock_config(void){
@@ -75,7 +71,7 @@ void usrp2_impl::update_clock_config(void){
void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){
//set ticks and seconds
this->poke32(FR_TIME64_SECS, time_spec.secs);
- this->poke32(FR_TIME64_TICKS, time_spec.ticks);
+ this->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq()));
//set the register to latch it all in
boost::uint32_t imm_flags = (now)? FRF_TIME64_LATCH_NOW : FRF_TIME64_LATCH_NEXT_PPS;
@@ -88,7 +84,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO);
out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0;
out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs);
- out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.ticks);
+ out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.get_ticks(get_master_clock_freq()));
//set these to defaults, then change in the switch statement
out_data.data.stream_cmd.continuous = 0;
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index a7be2da8c..6d8c1a86c 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -15,15 +15,16 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include "usrp2_impl.hpp"
#include <uhd/transport/if_addrs.hpp>
#include <uhd/usrp/device_props.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
+#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
#include <iostream>
-#include "usrp2_impl.hpp"
using namespace uhd;
using namespace uhd::usrp;
@@ -217,6 +218,35 @@ boost::uint16_t usrp2_impl::peek16(boost::uint32_t addr){
return impl_peek<boost::uint16_t>(this, addr);
}
+boost::uint32_t usrp2_impl::transact_spi(
+ int which_slave,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits,
+ bool readback
+){
+ static const uhd::dict<spi_config_t::edge_t, int> spi_edge_to_otw = boost::assign::map_list_of
+ (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE)
+ (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL)
+ ;
+
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO);
+ out_data.data.spi_args.dev = which_slave;
+ out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge];
+ out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge];
+ out_data.data.spi_args.readback = (readback)? 1 : 0;
+ out_data.data.spi_args.num_bits = num_bits;
+ out_data.data.spi_args.data = htonl(data);
+
+ //send and recv
+ usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE);
+
+ return ntohl(out_data.data.spi_args.data);
+}
+
/***********************************************************************
* Control Send/Recv
**********************************************************************/
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index baa6530b8..5a02b33dc 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -20,6 +20,7 @@
#include <uhd/usrp/usrp2.hpp>
#include <uhd/types/dict.hpp>
+#include <uhd/types/otw_type.hpp>
#include <uhd/types/stream_cmd.hpp>
#include <uhd/types/clock_config.hpp>
#include <boost/asio.hpp>
@@ -109,6 +110,15 @@ public:
void poke16(boost::uint32_t addr, boost::uint16_t data);
boost::uint16_t peek16(boost::uint32_t addr);
+ //spi read and write
+ boost::uint32_t transact_spi(
+ int which_slave,
+ const uhd::usrp::spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits,
+ bool readback
+ );
+
//misc access methods
double get_master_clock_freq(void);
@@ -136,9 +146,10 @@ private:
(_mtu - _hdrs)/sizeof(boost::uint32_t) -
uhd::transport::vrt::max_header_words32
;
- uhd::transport::smart_buffer::sptr _rx_smart_buff;
+ uhd::transport::managed_recv_buffer::sptr _rx_smart_buff;
boost::asio::const_buffer _rx_copy_buff;
size_t _fragment_offset_in_samps;
+ uhd::otw_type_t _otw_type;
void io_init(void);
//udp transports for control and data