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.cpp242
1 files changed, 242 insertions, 0 deletions
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
new file mode 100644
index 000000000..43334ddc6
--- /dev/null
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -0,0 +1,242 @@
+//
+// Copyright 2010 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <complex>
+#include <boost/shared_array.hpp>
+#include <boost/format.hpp>
+#include "usrp2_impl.hpp"
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * Constants
+ **********************************************************************/
+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;
+
+/***********************************************************************
+ * Helper Functions
+ **********************************************************************/
+static inline void host_floats_to_usrp2_shorts(
+ int16_t *usrp2_shorts,
+ const float *host_floats,
+ size_t num_samps
+){
+ for(size_t i = 0; i < num_samps; i++){
+ usrp2_shorts[i] = htons(int16_t(host_floats[i]*float_scale_factor));
+ }
+}
+
+static inline void usrp2_shorts_to_host_floats(
+ float *host_floats,
+ const int16_t *usrp2_shorts,
+ size_t num_samps
+){
+ for(size_t i = 0; i < num_samps; i++){
+ host_floats[i] = float(ntohs(usrp2_shorts[i])/float_scale_factor);
+ }
+}
+
+static inline void host_shorts_to_usrp2_shorts(
+ int16_t *usrp2_shorts,
+ const int16_t *host_shorts,
+ size_t num_samps
+){
+ for(size_t i = 0; i < num_samps; i++){
+ usrp2_shorts[i] = htons(host_shorts[i]);
+ }
+}
+
+static inline void usrp2_shorts_to_host_shorts(
+ int16_t *host_shorts,
+ const int16_t *usrp2_shorts,
+ size_t num_samps
+){
+ for(size_t i = 0; i < num_samps; i++){
+ host_shorts[i] = ntohs(usrp2_shorts[i]);
+ }
+}
+
+/***********************************************************************
+ * Send Raw Data
+ **********************************************************************/
+size_t usrp2_impl::send_raw(
+ const boost::asio::const_buffer &buff,
+ 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_flags = 0;
+ size_t num_vrt_hdr_words = 1;
+
+ //load the vrt header and flags
+ if(metadata.has_stream_id){
+ vrt_hdr_flags |= (0x1 << 28); //IF Data packet with Stream Identifier
+ vrt_hdr[num_vrt_hdr_words++] = htonl(metadata.stream_id);
+ }
+ if(metadata.has_time_spec){
+ vrt_hdr_flags |= (0x3 << 22) | (0x1 << 20); //TSI: Other, TSF: Sample Count Timestamp
+ vrt_hdr[num_vrt_hdr_words++] = htonl(metadata.time_spec.secs);
+ vrt_hdr[num_vrt_hdr_words++] = htonl(metadata.time_spec.ticks);
+ vrt_hdr[num_vrt_hdr_words++] = 0; //unused part of fractional seconds
+ }
+ vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0;
+ vrt_hdr_flags |= (metadata.end_of_burst)? (0x1 << 24) : 0;
+
+ //fill in complete header word
+ vrt_hdr[0] = htonl(vrt_hdr_flags |
+ ((_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) |
+ ((boost::asio::buffer_size(buff)/sizeof(uint32_t)) & 0xffff)
+ );
+
+ //load the buffer vector
+ size_t vrt_hdr_size = num_vrt_hdr_words*sizeof(uint32_t);
+ buffs[0] = boost::asio::buffer(&vrt_hdr, vrt_hdr_size);
+ buffs[1] = buff;
+
+ //send and return number of samples
+ return (_data_transport->send(buffs) - vrt_hdr_size)/sizeof(sc16_t);
+}
+
+/***********************************************************************
+ * Receive Raw Data
+ **********************************************************************/
+size_t usrp2_impl::recv_raw(
+ const boost::asio::mutable_buffer &buff,
+ uhd::metadata_t &metadata
+){
+ //load the buffer vector
+ std::vector<boost::asio::mutable_buffer> buffs(2);
+ uint32_t vrt_hdr[max_vrt_header_words];
+ buffs[0] = boost::asio::buffer(vrt_hdr, max_vrt_header_words);
+ buffs[1] = buff;
+
+ //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;
+
+ //unpack the vrt header
+ metadata = uhd::metadata_t();
+ uint32_t vrt_header = ntohl(vrt_hdr[0]);
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(vrt_hdr[1]);
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(vrt_hdr[2]);
+ metadata.time_spec.ticks = ntohl(vrt_hdr[3]);
+
+ //return the number of samples received
+ size_t num_words = vrt_header & 0xffff;
+ return (num_words*sizeof(uint32_t))/sizeof(sc16_t);
+}
+
+/***********************************************************************
+ * Send Data
+ **********************************************************************/
+size_t usrp2_impl::send(
+ const boost::asio::const_buffer &buff,
+ const uhd::metadata_t &metadata,
+ const std::string &type
+){
+ if (type == "fc32"){
+ size_t num_samps = boost::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));
+
+ host_floats_to_usrp2_shorts(
+ boost::asio::buffer_cast<int16_t*>(raw_buff),
+ boost::asio::buffer_cast<const float*>(buff),
+ num_samps*2 //double for complex
+ );
+
+ return send_raw(raw_buff, metadata);
+ }
+
+ if (type == "sc16"){
+ #ifdef HAVE_BIG_ENDIAN
+ return send_raw(buff, metadata);
+ #else
+ size_t num_samps = boost::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));
+
+ host_shorts_to_usrp2_shorts(
+ boost::asio::buffer_cast<int16_t*>(raw_buff),
+ boost::asio::buffer_cast<const int16_t*>(buff),
+ num_samps*2 //double for complex
+ );
+
+ return send_raw(raw_buff, metadata);
+ #endif
+ }
+
+ throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type));
+}
+
+/***********************************************************************
+ * Receive Data
+ **********************************************************************/
+size_t usrp2_impl::recv(
+ const boost::asio::mutable_buffer &buff,
+ uhd::metadata_t &metadata,
+ const std::string &type
+){
+ if (type == "fc32"){
+ size_t num_samps = boost::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));
+
+ num_samps = recv_raw(raw_buff, metadata);
+
+ usrp2_shorts_to_host_floats(
+ boost::asio::buffer_cast<float*>(buff),
+ boost::asio::buffer_cast<const int16_t*>(raw_buff),
+ num_samps*2 //double for complex
+ );
+
+ return num_samps;
+ }
+
+ if (type == "sc16"){
+ #ifdef HAVE_BIG_ENDIAN
+ return recv_raw(buff, metadata);
+ #else
+ size_t num_samps = boost::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));
+
+ num_samps = recv_raw(raw_buff, metadata);
+
+ usrp2_shorts_to_host_shorts(
+ boost::asio::buffer_cast<int16_t*>(buff),
+ boost::asio::buffer_cast<const int16_t*>(raw_buff),
+ num_samps*2 //double for complex
+ );
+
+ return num_samps;
+ #endif
+ }
+
+ throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%s\"") % type));
+}