aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/transport/CMakeLists.txt1
-rw-r--r--host/include/uhd/transport/vrt.hpp66
-rw-r--r--host/lib/CMakeLists.txt1
-rw-r--r--host/lib/transport/vrt.cpp104
-rw-r--r--host/test/CMakeLists.txt1
-rw-r--r--host/test/vrt_test.cpp97
6 files changed, 270 insertions, 0 deletions
diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt
index ba8b33cc5..7f5db2128 100644
--- a/host/include/uhd/transport/CMakeLists.txt
+++ b/host/include/uhd/transport/CMakeLists.txt
@@ -20,5 +20,6 @@ INSTALL(FILES
smart_buffer.hpp
udp_simple.hpp
udp_zero_copy.hpp
+ vrt.hpp
DESTINATION ${HEADER_DIR}/uhd/transport
)
diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp
new file mode 100644
index 000000000..b56da4077
--- /dev/null
+++ b/host/include/uhd/transport/vrt.hpp
@@ -0,0 +1,66 @@
+//
+// 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 <uhd/metadata.hpp>
+#include <cstddef>
+
+#ifndef INCLUDED_UHD_TRANSPORT_VRT_HPP
+#define INCLUDED_UHD_TRANSPORT_VRT_HPP
+
+namespace uhd{ namespace transport{
+
+namespace vrt{
+
+ static const size_t max_header_words32 = 7;
+
+ /*!
+ * Pack a vrt header from metadata.
+ * \param metadata the tx metadata with flags and timestamps
+ * \param header_buff memory to write the packed vrt header
+ * \param num_header_words32 number of words in the vrt header
+ * \param num_payload_words32 the length of the payload
+ * \param packet_count the packet count sequence number
+ */
+ void pack(
+ const metadata_t &metadata, //input
+ uint32_t *header_buff, //output
+ size_t &num_header_words32, //output
+ size_t num_payload_words32, //input
+ size_t packet_count //input
+ );
+
+ /*!
+ * Unpack a vrt header to metadata.
+ * \param metadata the rx metadata with flags and timestamps
+ * \param header_buff memory to read the packed vrt header
+ * \param num_header_words32 number of words in the vrt header
+ * \param num_payload_words32 the length of the payload
+ * \param packet_count the packet count sequence number
+ */
+ void unpack(
+ metadata_t &metadata, //output
+ const uint32_t *header_buff, //input
+ size_t &num_header_words32, //output
+ size_t &num_payload_words32, //output
+ size_t &packet_count //output
+ );
+
+} //namespace vrt
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_TRANSPORT_VRT_HPP */
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index a52cd74a9..390349906 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -24,6 +24,7 @@ SET(libuhd_sources
gain_handler.cpp
wax.cpp
transport/udp_simple.cpp
+ transport/vrt.cpp
usrp/dboard/basic.cpp
usrp/dboard_base.cpp
usrp/dboard_id.cpp
diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp
new file mode 100644
index 000000000..40b26d31f
--- /dev/null
+++ b/host/lib/transport/vrt.cpp
@@ -0,0 +1,104 @@
+//
+// 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 <uhd/transport/vrt.hpp>
+#include <netinet/in.h>
+#include <stdexcept>
+
+using namespace uhd::transport;
+
+void vrt::pack(
+ const metadata_t &metadata, //input
+ uint32_t *header_buff, //output
+ size_t &num_header_words32, //output
+ size_t num_payload_words32, //input
+ size_t packet_count //input
+){
+ uint32_t vrt_hdr_flags = 0;
+ num_header_words32 = 1;
+
+ //load the vrt header and flags
+ if(metadata.has_stream_id){
+ vrt_hdr_flags |= (0x1 << 28); //IF Data packet with Stream Identifier
+ header_buff[num_header_words32++] = htonl(metadata.stream_id);
+ }
+
+ if(metadata.has_time_spec){
+ vrt_hdr_flags |= (0x3 << 22) | (0x1 << 20); //TSI: Other, TSF: Sample Count Timestamp
+ header_buff[num_header_words32++] = htonl(metadata.time_spec.secs);
+ header_buff[num_header_words32++] = htonl(metadata.time_spec.ticks);
+ header_buff[num_header_words32++] = 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
+ header_buff[0] = htonl(vrt_hdr_flags |
+ ((packet_count & 0xf) << 16) |
+ ((num_header_words32 + num_payload_words32) & 0xffff)
+ );
+}
+
+void vrt::unpack(
+ metadata_t &metadata, //output
+ const uint32_t *header_buff, //input
+ size_t &num_header_words32, //output
+ size_t &num_payload_words32, //output
+ size_t &packet_count //output
+){
+ //clear the metadata
+ metadata = metadata_t();
+
+ //extract vrt header
+ uint32_t vrt_hdr_word = ntohl(header_buff[0]);
+ size_t packet_words32 = vrt_hdr_word & 0xffff;
+ packet_count = (vrt_hdr_word >> 16) & 0xf;
+
+ //failure cases
+ if (packet_words32 == 0) //FIXME check the packet length before we continue
+ throw std::runtime_error("bad vrt header");
+ if (vrt_hdr_word & (0x7 << 29))
+ throw std::runtime_error("unsupported vrt packet type");
+
+ //parse the header flags
+ num_header_words32 = 1;
+
+ if (vrt_hdr_word & (0x1 << 28)){ //stream id
+ metadata.has_stream_id = true;
+ metadata.stream_id = ntohl(header_buff[num_header_words32++]);
+ }
+
+ if (vrt_hdr_word & (0x1 << 27)){ //class id (we dont use)
+ num_header_words32 += 2;
+ }
+
+ if (vrt_hdr_word & (0x3 << 22)){ //integer time
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = ntohl(header_buff[num_header_words32++]);
+ }
+
+ if (vrt_hdr_word & (0x3 << 20)){ //fractional time
+ metadata.has_time_spec = true;
+ metadata.time_spec.ticks = ntohl(header_buff[num_header_words32++]);
+ num_header_words32++; //unused part of fractional seconds
+ }
+
+ size_t num_trailer_words32 = (vrt_hdr_word & (0x1 << 26))? 1 : 0;
+
+ num_payload_words32 = packet_words32 - num_header_words32 - num_trailer_words32;
+}
diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt
index 234b6f92c..b1d5924c7 100644
--- a/host/test/CMakeLists.txt
+++ b/host/test/CMakeLists.txt
@@ -20,6 +20,7 @@ ADD_EXECUTABLE(main_test
main_test.cpp
addr_test.cpp
gain_handler_test.cpp
+ vrt_test.cpp
wax_test.cpp
)
diff --git a/host/test/vrt_test.cpp b/host/test/vrt_test.cpp
new file mode 100644
index 000000000..9b2d43430
--- /dev/null
+++ b/host/test/vrt_test.cpp
@@ -0,0 +1,97 @@
+//
+// 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 <boost/test/unit_test.hpp>
+#include <uhd/transport/vrt.hpp>
+
+using namespace uhd::transport;
+
+static void pack_and_unpack(
+ const uhd::metadata_t &metadata,
+ size_t num_payload_words32,
+ size_t packet_count
+){
+ uint32_t header_buff[vrt::max_header_words32];
+ size_t num_header_words32;
+
+ //pack metadata into a vrt header
+ vrt::pack(
+ metadata, //input
+ header_buff, //output
+ num_header_words32, //output
+ num_payload_words32, //input
+ packet_count //input
+ );
+
+ uhd::metadata_t metadata_out;
+ size_t num_header_words32_out;
+ size_t num_payload_words32_out;
+ size_t packet_count_out;
+
+ //unpack the vrt header back into metadata
+ vrt::unpack(
+ metadata_out, //output
+ header_buff, //input
+ num_header_words32_out, //output
+ num_payload_words32_out, //output
+ packet_count_out //output
+ );
+
+ //check the the unpacked metadata is the same
+ BOOST_CHECK_EQUAL(packet_count, packet_count_out);
+ BOOST_CHECK_EQUAL(num_header_words32, num_header_words32_out);
+ BOOST_CHECK_EQUAL(num_payload_words32, num_payload_words32_out);
+ BOOST_CHECK_EQUAL(metadata.has_stream_id, metadata_out.has_stream_id);
+ if (metadata.has_stream_id and metadata_out.has_stream_id){
+ BOOST_CHECK_EQUAL(metadata.stream_id, metadata_out.stream_id);
+ }
+ BOOST_CHECK_EQUAL(metadata.has_time_spec, metadata_out.has_time_spec);
+ if (metadata.has_time_spec and metadata_out.has_time_spec){
+ BOOST_CHECK_EQUAL(metadata.time_spec.secs, metadata_out.time_spec.secs);
+ BOOST_CHECK_EQUAL(metadata.time_spec.ticks, metadata_out.time_spec.ticks);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_with_none){
+ uhd::metadata_t metadata;
+ pack_and_unpack(metadata, 300, 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_with_sid){
+ uhd::metadata_t metadata;
+ metadata.has_stream_id = true;
+ metadata.stream_id = 6;
+ pack_and_unpack(metadata, 400, 2);
+}
+
+BOOST_AUTO_TEST_CASE(test_with_time_spec){
+ uhd::metadata_t metadata;
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = 7;
+ metadata.time_spec.ticks = 2000;
+ pack_and_unpack(metadata, 500, 3);
+}
+
+BOOST_AUTO_TEST_CASE(test_with_sid_and_time_spec){
+ uhd::metadata_t metadata;
+ metadata.has_stream_id = true;
+ metadata.stream_id = 2;
+ metadata.has_time_spec = true;
+ metadata.time_spec.secs = 5;
+ metadata.time_spec.ticks = 1000;
+ pack_and_unpack(metadata, 600, 4);
+}