From 6b7c53985c09a8d74e9bfd9c6b37948d458b2c44 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 22 Feb 2010 18:47:05 -0800 Subject: Work on the io interface for a device (and some implementation work in usrp2). Modified the udp transport to reflect some of these changes. Got the fw compiling again, and it will not set data to true for small payloads (configuration ones). --- firmware/microblaze/apps/Makefile.am | 2 +- firmware/microblaze/apps/txrx.c | 5 ++- host/CMakeLists.txt | 9 +++++ host/include/uhd/CMakeLists.txt | 1 + host/include/uhd/device.hpp | 33 +++++++++++++--- host/include/uhd/metadata.hpp | 47 +++++++++++++++++++++++ host/include/uhd/transport/udp.hpp | 17 ++++++++- host/lib/transport/udp.cpp | 20 ++++++---- host/lib/usrp/usrp2/usrp2_impl.cpp | 74 ++++++++++++++++++++++++++++++++++-- host/lib/usrp/usrp2/usrp2_impl.hpp | 4 +- 10 files changed, 189 insertions(+), 23 deletions(-) create mode 100644 host/include/uhd/metadata.hpp diff --git a/firmware/microblaze/apps/Makefile.am b/firmware/microblaze/apps/Makefile.am index 6d993ef8c..ff426cf8c 100644 --- a/firmware/microblaze/apps/Makefile.am +++ b/firmware/microblaze/apps/Makefile.am @@ -21,7 +21,7 @@ include $(top_srcdir)/Makefile.common LDADD = $(top_srcdir)/lib/libu2fw.a -AM_CFLAGS += -I$(top_srcdir)/../../host/lib/usrp/mboard +AM_CFLAGS += -I$(top_srcdir)/../../host/lib/usrp noinst_PROGRAMS = txrx.elf diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 77c8e498c..16aa8eab2 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -159,7 +159,10 @@ void handle_udp_data_packet( unsigned char *payload, int payload_len ){ //TODO store the reply port - _is_data = true; + + //forward this data to the dsp when the payload is sufficient + //the small payload is used to give the device the udp source port + _is_data = payload_len > sizeof(uint32_t); } #define OTW_GPIO_BANK_TO_NUM(bank) \ diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 70c04631b..30f4789a3 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -72,6 +72,15 @@ FIND_PACKAGE(Boost 1.36 REQUIRED INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) +######################################################################## +# Setup Endianess +######################################################################## +INCLUDE(TestBigEndian) +TEST_BIG_ENDIAN(HAVE_BIG_ENDIAN) +IF(HAVE_BIG_ENDIAN) + ADD_DEFINITIONS("-DHAVE_BIG_ENDIAN=/* */") +ENDIF(HAVE_BIG_ENDIAN) + ######################################################################## # Create Uninstall Target ######################################################################## diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 006c54f22..e87f74291 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -24,6 +24,7 @@ INSTALL(FILES device_addr.hpp dict.hpp gain_handler.hpp + metadata.hpp props.hpp shared_iovec.hpp time_spec.hpp diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index dfbfbd7c0..da58d4f85 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -20,13 +20,12 @@ #include #include +#include #include #include #include #include #include -#include -#include namespace uhd{ @@ -72,9 +71,33 @@ public: */ device_addr_t get_device_addr(void); - //the io interface - virtual void send_raw(const std::vector &) = 0; - virtual uhd::shared_iovec recv_raw(void) = 0; + /*! + * Send a buffer containing IF data with its metadata. + * + * \param buff a buffer pointing to some read-only memory + * \param metadata data describing the buffer's contents + * \param the type of data loaded in the buffer (32fc, 16sc) + * \return the number of bytes sent + */ + virtual size_t send( + const boost::asio::const_buffer &buff, + const metadata_t &metadata, + const std::string &type = "32fc" + ) = 0; + + /*! + * Receive a buffer containing IF data and its metadata. + * + * \param buff the buffer to fill with IF data + * \param metadata data to fill describing the buffer + * \param the type of data to fill into the buffer (32fc, 16sc) + * \return the number of bytes received + */ + virtual size_t recv( + const boost::asio::mutable_buffer &buff, + metadata_t &metadata, + const std::string &type = "32fc" + ) = 0; }; } //namespace uhd diff --git a/host/include/uhd/metadata.hpp b/host/include/uhd/metadata.hpp new file mode 100644 index 000000000..43b91d1b0 --- /dev/null +++ b/host/include/uhd/metadata.hpp @@ -0,0 +1,47 @@ +// +// 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 . +// + +#ifndef INCLUDED_UHD_METADATA_HPP +#define INCLUDED_UHD_METADATA_HPP + +#include + +namespace uhd{ + +/*! + * Metadata structure for describing the IF data. + * Includes stream ID, time specification, and burst flags. + * The receive routines will convert IF data headers into metadata. + * The send routines will convert the metadata to IF data headers. + */ +struct metadata_t{ + uint32_t stream_id; + time_spec_t time_spec; + bool start_of_burst; + bool end_of_burst; + + metadata_t(void){ + stream_id = 0; + time_spec = time_spec_t(); + start_of_burst = false; + end_of_burst = false; + } +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_METADATA_HPP */ diff --git a/host/include/uhd/transport/udp.hpp b/host/include/uhd/transport/udp.hpp index 554234b43..07d84e62a 100644 --- a/host/include/uhd/transport/udp.hpp +++ b/host/include/uhd/transport/udp.hpp @@ -41,18 +41,31 @@ public: /*! * Send a vector of buffer (like send_msg). + * Blocks until the data is sent. * \param buffs a vector of asio buffers + * \return the number of bytes sent */ - virtual void send(const std::vector &buffs) = 0; + virtual size_t send(const std::vector &buffs) = 0; /*! * Send a single buffer. + * Blocks until the data is sent. * \param buff single asio buffer + * \return the number of bytes sent */ - virtual void send(const boost::asio::const_buffer &buff) = 0; + virtual size_t send(const boost::asio::const_buffer &buff) = 0; + + /*! + * Receive a buffer. Write into the memory provided. + * Returns empty when data is not available. + * \param buff a mutable buffer to receive into + * \return the number of bytes received. + */ + virtual size_t recv(const boost::asio::mutable_buffer &buff) = 0; /*! * Receive a buffer. The memory is managed internally. + * Returns zero when data is not available. * Calling recv will invalidate the buffer of the previous recv. * \return a shared iovec with allocated memory */ diff --git a/host/lib/transport/udp.cpp b/host/lib/transport/udp.cpp index af60760a5..fca4dd7d6 100644 --- a/host/lib/transport/udp.cpp +++ b/host/lib/transport/udp.cpp @@ -17,7 +17,6 @@ #include #include -#include #include /*********************************************************************** @@ -30,8 +29,9 @@ public: ~udp_impl(void); //send/recv - void send(const std::vector &buffs); - void send(const boost::asio::const_buffer &buff); + size_t send(const std::vector &buffs); + size_t send(const boost::asio::const_buffer &buff); + size_t recv(const boost::asio::mutable_buffer &buff); uhd::shared_iovec recv(void); private: @@ -79,13 +79,17 @@ udp_impl::~udp_impl(void){ delete _socket; } -void udp_impl::send(const std::vector &buffs){ - _socket->send_to(buffs, _receiver_endpoint); +size_t udp_impl::send(const std::vector &buffs){ + return _socket->send_to(buffs, _receiver_endpoint); } -void udp_impl::send(const boost::asio::const_buffer &buff){ - std::vector buffs = boost::assign::list_of(buff); - send(buffs); +size_t udp_impl::send(const boost::asio::const_buffer &buff){ + return _socket->send_to(boost::asio::buffer(buff), _receiver_endpoint); +} + +size_t udp_impl::recv(const boost::asio::mutable_buffer &buff){ + if (_socket->available() == 0) return 0; + return _socket->receive_from(boost::asio::buffer(buff), _sender_endpoint); } uhd::shared_iovec udp_impl::recv(void){ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index f44964394..47bf06aff 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -130,6 +130,10 @@ usrp2_impl::usrp2_impl( //init the tx and rx dboards (do last) dboard_init(); + //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))); + } usrp2_impl::~usrp2_impl(void){ @@ -204,10 +208,72 @@ void usrp2_impl::set(const wax::obj &, const wax::obj &){ /*********************************************************************** * IO Interface **********************************************************************/ -void usrp2_impl::send_raw(const std::vector &){ - return; +static const float float_scale_factor = pow(2.0, 15); + +size_t usrp2_impl::send( + const boost::asio::const_buffer &buff, + const uhd::metadata_t &metadata, + const std::string &type +){ + if (type == "fc32"){ + //extract the buffer elements + const float *float_buff = boost::asio::buffer_cast(buff); + const size_t buff_len = boost::asio::buffer_size(buff)/sizeof(float); + + //convert floats into the shorts buffer + int16_t *shorts_buff = new int16_t[buff_len]; + for (size_t i = 0; i < buff_len; i++){ + shorts_buff[i] = float_buff[i]*float_scale_factor; + } + + //send from a buffer of shorts + size_t bytes_sent = send( + boost::asio::buffer(shorts_buff, buff_len*sizeof(int16_t)), + metadata, "sc16" + ); + + //cleanup + delete [] shorts_buff; + return bytes_sent; + } + + if (type == "sc16"){ + throw std::runtime_error("not implemented"); + } + + throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type)); } -uhd::shared_iovec usrp2_impl::recv_raw(void){ - throw std::runtime_error("not implemented"); +size_t usrp2_impl::recv( + const boost::asio::mutable_buffer &buff, + uhd::metadata_t &metadata, + const std::string &type +){ + if (type == "fc32"){ + //extract the buffer elements + float *float_buff = boost::asio::buffer_cast(buff); + const size_t buff_len = boost::asio::buffer_size(buff)/sizeof(float); + + //receive into a buffer of shorts + int16_t *shorts_buff = new int16_t[buff_len]; + size_t bytes_received = recv( + boost::asio::buffer(shorts_buff, buff_len*sizeof(int16_t)), + metadata, "sc16" + ); + + //convert floats into the shorts buffer + for (size_t i = 0; i < bytes_received/sizeof(int16_t); i++){ + float_buff[i] = shorts_buff[i]/float_scale_factor; + } + + //cleanup + delete [] shorts_buff; + return bytes_received; + } + + if (type == "sc16"){ + throw std::runtime_error("not implemented"); + } + + throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%s\"") % type)); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 2545efd58..2476bcf1d 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -98,8 +98,8 @@ public: double get_master_clock_freq(void); //the io interface - void send_raw(const std::vector &); - uhd::shared_iovec recv_raw(void); + size_t send(const boost::asio::const_buffer &, const uhd::metadata_t &, const std::string &); + size_t recv(const boost::asio::mutable_buffer &, uhd::metadata_t &, const std::string &); private: //udp transports for control and data -- cgit v1.2.3