diff options
| author | Josh Blum <josh@joshknows.com> | 2010-03-02 23:56:19 -0800 | 
|---|---|---|
| committer | Josh Blum <josh@joshknows.com> | 2010-03-02 23:56:19 -0800 | 
| commit | 8e8221dc380fb275a17dcd0abbfaea108f44505f (patch) | |
| tree | f2e1c298f6131a48272b3e612dd3b21ed6eee129 | |
| parent | 4efafcc2e20b9a980800a979edf5ea7a493b6462 (diff) | |
| download | uhd-8e8221dc380fb275a17dcd0abbfaea108f44505f.tar.gz uhd-8e8221dc380fb275a17dcd0abbfaea108f44505f.tar.bz2 uhd-8e8221dc380fb275a17dcd0abbfaea108f44505f.zip | |
Added a vrt library to pack and unpack from metadata.
Added a vrt test app that packs and unpacks the data.
| -rw-r--r-- | host/include/uhd/transport/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/include/uhd/transport/vrt.hpp | 66 | ||||
| -rw-r--r-- | host/lib/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/lib/transport/vrt.cpp | 104 | ||||
| -rw-r--r-- | host/test/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/test/vrt_test.cpp | 97 | 
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); +} | 
