aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/usrp2/io_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/usrp2/io_impl.cpp')
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp153
1 files changed, 89 insertions, 64 deletions
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 9c7a41e49..8b45a708a 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -16,7 +16,6 @@
//
#include <complex>
-#include <boost/shared_array.hpp>
#include <boost/format.hpp>
#include "usrp2_impl.hpp"
@@ -27,55 +26,80 @@ namespace asio = boost::asio;
/***********************************************************************
* Constants
**********************************************************************/
-typedef std::complex<float> fc32_t;
-typedef std::complex<short> sc16_t;
+typedef std::complex<float> fc32_t;
+typedef std::complex<int16_t> sc16_t;
-static const float float_scale_factor = pow(2.0, 15);
-
-//max length with header, stream id, seconds, fractional seconds
-static const size_t max_vrt_header_words = 5;
+static const float shorts_per_float = pow(2.0, 15);
+static const float floats_per_short = 1.0/shorts_per_float;
/***********************************************************************
* Helper Functions
**********************************************************************/
-static inline void host_floats_to_usrp2_shorts(
- short *usrp2_shorts,
- const float *host_floats,
+void usrp2_impl::io_init(void){
+ //initially empty spillover buffer
+ _splillover_buff = asio::buffer(_spillover_mem, 0);
+
+ //send a small data packet so the usrp2 knows the udp source port
+ uint32_t zero_data = 0;
+ _data_transport->send(boost::asio::buffer(&zero_data, sizeof(zero_data)));
+}
+
+#define unrolled_loop(__i, __len, __inst) {\
+ size_t __i = 0; \
+ while(__i < (__len & ~0x7)){ \
+ __inst; __i++; __inst; __i++; \
+ __inst; __i++; __inst; __i++; \
+ __inst; __i++; __inst; __i++; \
+ __inst; __i++; __inst; __i++; \
+ } \
+ while(__i < __len){ \
+ __inst; __i++;\
+ } \
+}
+
+static inline void host_floats_to_usrp2_items(
+ uint32_t *usrp2_items,
+ const fc32_t *host_floats,
size_t num_samps
){
- for(size_t i = 0; i < num_samps; i++){
- usrp2_shorts[i] = htons(short(host_floats[i]*float_scale_factor));
- }
+ unrolled_loop(i, num_samps,{
+ int16_t real = host_floats[i].real()*shorts_per_float;
+ int16_t imag = host_floats[i].imag()*shorts_per_float;
+ usrp2_items[i] = htonl(((real << 16) & 0xffff) | ((imag << 0) & 0xffff));
+ });
}
-static inline void usrp2_shorts_to_host_floats(
- float *host_floats,
- const short *usrp2_shorts,
+static inline void usrp2_items_to_host_floats(
+ fc32_t *host_floats,
+ const uint32_t *usrp2_items,
size_t num_samps
){
- for(size_t i = 0; i < num_samps; i++){
- host_floats[i] = float(short(ntohs(usrp2_shorts[i])))/float_scale_factor;
- }
+ unrolled_loop(i, num_samps,{
+ uint32_t item = ntohl(usrp2_items[i]);
+ int16_t real = (item >> 16) & 0xffff;
+ int16_t imag = (item >> 0) & 0xffff;
+ host_floats[i] = fc32_t(real*floats_per_short, imag*floats_per_short);
+ });
}
-static inline void host_shorts_to_usrp2_shorts(
- short *usrp2_shorts,
- const short *host_shorts,
+static inline void host_items_to_usrp2_items(
+ uint32_t *usrp2_items,
+ const uint32_t *host_items,
size_t num_samps
){
- for(size_t i = 0; i < num_samps; i++){
- usrp2_shorts[i] = htons(host_shorts[i]);
- }
+ unrolled_loop(i, num_samps,
+ usrp2_items[i] = htonl(host_items[i])
+ );
}
-static inline void usrp2_shorts_to_host_shorts(
- short *host_shorts,
- const short *usrp2_shorts,
+static inline void usrp2_items_to_host_items(
+ uint32_t *host_items,
+ const uint32_t *usrp2_items,
size_t num_samps
){
- for(size_t i = 0; i < num_samps; i++){
- host_shorts[i] = ntohs(usrp2_shorts[i]);
- }
+ unrolled_loop(i, num_samps,
+ host_items[i] = ntohl(usrp2_items[i])
+ );
}
/***********************************************************************
@@ -86,7 +110,7 @@ size_t usrp2_impl::send_raw(
const uhd::metadata_t &metadata
){
std::vector<boost::asio::const_buffer> buffs(2);
- uint32_t vrt_hdr[max_vrt_header_words];
+ uint32_t vrt_hdr[7]; //max size
uint32_t vrt_hdr_flags = 0;
size_t num_vrt_hdr_words = 1;
@@ -107,7 +131,7 @@ size_t usrp2_impl::send_raw(
//fill in complete header word
vrt_hdr[0] = htonl(vrt_hdr_flags |
- ((_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) |
+ ((_tx_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) |
(num_vrt_hdr_words & 0xffff)
);
@@ -148,18 +172,16 @@ size_t usrp2_impl::recv_raw(
//load the buffer vector
std::vector<boost::asio::mutable_buffer> buffs(3);
- uint32_t vrt_hdr[max_vrt_header_words];
- buffs[0] = asio::buffer(vrt_hdr, max_vrt_header_words*sizeof(uint32_t));
- buffs[1] = asio::buffer(//make sure its on a word boundary
- buff, asio::buffer_size(buff) & ~(sizeof(uint32_t) - 1)
- );
+ uint32_t vrt_hdr[USRP2_HOST_RX_VRT_HEADER_WORDS32];
+ buffs[0] = asio::buffer(vrt_hdr, sizeof(vrt_hdr));
+ buffs[1] = buff;
buffs[2] = asio::buffer(_spillover_mem, _mtu);
//receive into the buffers
size_t bytes_recvd = _data_transport->recv(buffs);
//failure case
- if (bytes_recvd < max_vrt_header_words*sizeof(uint32_t)) return 0;
+ if (bytes_recvd < sizeof(vrt_hdr)) return 0;
//unpack the vrt header
metadata = uhd::metadata_t();
@@ -170,8 +192,15 @@ size_t usrp2_impl::recv_raw(
metadata.time_spec.secs = ntohl(vrt_hdr[2]);
metadata.time_spec.ticks = ntohl(vrt_hdr[3]);
+ size_t my_seq = (vrt_header >> 16) & 0xf;
+ //std::cout << "seq " << my_seq << std::endl;
+ if (my_seq != ((_rx_stream_id_to_packet_seq[metadata.stream_id]+1) & 0xf)) std::cout << "bad seq " << my_seq << std::endl;
+ _rx_stream_id_to_packet_seq[metadata.stream_id] = my_seq;
+
//extract the number of bytes received
- size_t num_words = (vrt_header & 0xffff) - max_vrt_header_words;
+ size_t num_words = (vrt_header & 0xffff);
+ num_words -= USRP2_HOST_RX_VRT_HEADER_WORDS32;
+ num_words -= USRP2_HOST_RX_VRT_TRAILER_WORDS32;
size_t num_bytes = num_words*sizeof(uint32_t);
//handle the case where spillover memory was used
@@ -191,13 +220,12 @@ size_t usrp2_impl::send(
){
if (type == "32fc"){
size_t num_samps = asio::buffer_size(buff)/sizeof(fc32_t);
- boost::shared_array<sc16_t> raw_mem(new sc16_t[num_samps]);
- boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t));
+ boost::asio::mutable_buffer raw_buff(_tmp_send_mem, num_samps*sizeof(sc16_t));
- host_floats_to_usrp2_shorts(
- asio::buffer_cast<short*>(raw_buff),
- asio::buffer_cast<const float*>(buff),
- num_samps*2 //double for complex
+ host_floats_to_usrp2_items(
+ asio::buffer_cast<uint32_t*>(raw_buff),
+ asio::buffer_cast<const fc32_t*>(buff),
+ num_samps
);
return send_raw(raw_buff, metadata);
@@ -208,13 +236,12 @@ size_t usrp2_impl::send(
return send_raw(buff, metadata);
#else
size_t num_samps = asio::buffer_size(buff)/sizeof(sc16_t);
- boost::shared_array<sc16_t> raw_mem(new sc16_t[num_samps]);
- boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t));
+ boost::asio::mutable_buffer raw_buff(_tmp_send_mem, num_samps*sizeof(sc16_t));
- host_shorts_to_usrp2_shorts(
- asio::buffer_cast<short*>(raw_buff),
- asio::buffer_cast<const short*>(buff),
- num_samps*2 //double for complex
+ host_items_to_usrp2_items(
+ asio::buffer_cast<uint32_t*>(raw_buff),
+ asio::buffer_cast<const uint32_t*>(buff),
+ num_samps
);
return send_raw(raw_buff, metadata);
@@ -234,15 +261,14 @@ size_t usrp2_impl::recv(
){
if (type == "32fc"){
size_t num_samps = asio::buffer_size(buff)/sizeof(fc32_t);
- boost::shared_array<sc16_t> raw_mem(new sc16_t[num_samps]);
- boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t));
+ boost::asio::mutable_buffer raw_buff(_tmp_recv_mem, num_samps*sizeof(sc16_t));
num_samps = recv_raw(raw_buff, metadata);
- usrp2_shorts_to_host_floats(
- asio::buffer_cast<float*>(buff),
- asio::buffer_cast<const short*>(raw_buff),
- num_samps*2 //double for complex
+ usrp2_items_to_host_floats(
+ asio::buffer_cast<fc32_t*>(buff),
+ asio::buffer_cast<const uint32_t*>(raw_buff),
+ num_samps
);
return num_samps;
@@ -253,15 +279,14 @@ size_t usrp2_impl::recv(
return recv_raw(buff, metadata);
#else
size_t num_samps = asio::buffer_size(buff)/sizeof(sc16_t);
- boost::shared_array<sc16_t> raw_mem(new sc16_t[num_samps]);
- boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t));
+ boost::asio::mutable_buffer raw_buff(_tmp_recv_mem, num_samps*sizeof(sc16_t));
num_samps = recv_raw(raw_buff, metadata);
- usrp2_shorts_to_host_shorts(
- asio::buffer_cast<short*>(buff),
- asio::buffer_cast<const short*>(raw_buff),
- num_samps*2 //double for complex
+ usrp2_items_to_host_items(
+ asio::buffer_cast<uint32_t*>(buff),
+ asio::buffer_cast<const uint32_t*>(raw_buff),
+ num_samps
);
return num_samps;