From d42e588d76efc41d18dabc75027347fe123904d1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 22 Feb 2010 11:42:32 -0800 Subject: Moved the udp implementation guts into the cpp file --- host/lib/usrp/usrp2/usrp2_impl.cpp | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2b4e8fe39..f44964394 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -33,17 +33,18 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ //create a udp transport to communicate //TODO if an addr is not provided, search all interfaces? std::string ctrl_port = boost::lexical_cast(USRP2_UDP_CTRL_PORT); - uhd::transport::udp udp_transport(hint["addr"], ctrl_port, true); + transport::udp::sptr udp_transport = \ + transport::udp::make(hint["addr"], ctrl_port, true); //send a hello control packet usrp2_ctrl_data_t ctrl_data_out; ctrl_data_out.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); - udp_transport.send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); + udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); //loop and recieve until the time is up size_t num_timeouts = 0; while(true){ - uhd::shared_iovec iov = udp_transport.recv(); + uhd::shared_iovec iov = udp_transport->recv(); //std::cout << boost::asio::buffer_size(buff) << "\n"; if (iov.len < sizeof(usrp2_ctrl_data_t)){ //sleep a little so we dont burn cpu @@ -72,21 +73,17 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ /*********************************************************************** * Make **********************************************************************/ +#define num2str(num) (boost::lexical_cast(num)) + device::sptr usrp2::make(const device_addr_t &device_addr){ //create a control transport - uhd::transport::udp::sptr ctrl_transport( - new uhd::transport::udp( - device_addr["addr"], - boost::lexical_cast(USRP2_UDP_CTRL_PORT) - ) + transport::udp::sptr ctrl_transport = transport::udp::make( + device_addr["addr"], num2str(USRP2_UDP_CTRL_PORT) ); //create a data transport - uhd::transport::udp::sptr data_transport( - new uhd::transport::udp( - device_addr["addr"], - boost::lexical_cast(USRP2_UDP_DATA_PORT) - ) + transport::udp::sptr data_transport = transport::udp::make( + device_addr["addr"], num2str(USRP2_UDP_DATA_PORT) ); //create the usrp2 implementation guts @@ -99,8 +96,8 @@ device::sptr usrp2::make(const device_addr_t &device_addr){ * Structors **********************************************************************/ usrp2_impl::usrp2_impl( - uhd::transport::udp::sptr ctrl_transport, - uhd::transport::udp::sptr data_transport + transport::udp::sptr ctrl_transport, + transport::udp::sptr data_transport ){ _ctrl_transport = ctrl_transport; _data_transport = data_transport; @@ -121,9 +118,6 @@ usrp2_impl::usrp2_impl( //init the mboard mboard_init(); - //init the tx and rx dboards - dboard_init(); - //init the ddc init_ddc_config(); @@ -132,6 +126,10 @@ usrp2_impl::usrp2_impl( //initialize the clock configuration init_clock_config(); + + //init the tx and rx dboards (do last) + dboard_init(); + } usrp2_impl::~usrp2_impl(void){ -- cgit v1.2.3 From 5200303517f4941fa60e2db713411f36116634a7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 22 Feb 2010 14:36:48 -0800 Subject: added set nice gpio pins to manager on init and deconstruct --- host/lib/usrp/dboard_manager.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index f0846db25..cce239f3e 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -91,6 +91,8 @@ private: //the subdevice proxy is internal to the cpp file uhd::dict _rx_dboards; uhd::dict _tx_dboards; + dboard_interface::sptr _interface; + void set_nice_gpio_pins(void); }; /*********************************************************************** @@ -184,6 +186,7 @@ dboard_manager_impl::dboard_manager_impl( dboard_interface::sptr interface ){ register_internal_dboards(); //always call first + _interface = interface; dboard_ctor_t rx_dboard_ctor; prop_names_t rx_subdevs; boost::tie(rx_dboard_ctor, rx_subdevs) = get_dboard_args(rx_dboard_id, "rx"); @@ -192,14 +195,7 @@ dboard_manager_impl::dboard_manager_impl( boost::tie(tx_dboard_ctor, tx_subdevs) = get_dboard_args(tx_dboard_id, "tx"); //initialize the gpio pins before creating subdevs - interface->set_gpio_ddr(dboard_interface::GPIO_RX_BANK, 0x0000, 0xffff); //all inputs - interface->set_gpio_ddr(dboard_interface::GPIO_TX_BANK, 0x0000, 0xffff); - - interface->write_gpio(dboard_interface::GPIO_RX_BANK, 0x0000, 0xffff); //all zeros - interface->write_gpio(dboard_interface::GPIO_TX_BANK, 0x0000, 0xffff); - - interface->set_atr_reg(dboard_interface::GPIO_RX_BANK, 0x0000, 0x0000, 0x0000); //software controlled - interface->set_atr_reg(dboard_interface::GPIO_TX_BANK, 0x0000, 0x0000, 0x0000); + set_nice_gpio_pins(); //make xcvr subdevs (make one subdev for both rx and tx dboards) if (rx_dboard_ctor == tx_dboard_ctor){ @@ -245,7 +241,7 @@ dboard_manager_impl::dboard_manager_impl( } dboard_manager_impl::~dboard_manager_impl(void){ - /* NOP */ + set_nice_gpio_pins(); } prop_names_t dboard_manager_impl::get_rx_subdev_names(void){ @@ -271,3 +267,16 @@ wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ //get a link to the tx subdev proxy return wax::cast(_tx_dboards[subdev_name])->get_link(); } + +void dboard_manager_impl::set_nice_gpio_pins(void){ + //std::cout << "Set nice GPIO pins" << std::endl; + + _interface->set_gpio_ddr(dboard_interface::GPIO_RX_BANK, 0x0000, 0xffff); //all inputs + _interface->set_gpio_ddr(dboard_interface::GPIO_TX_BANK, 0x0000, 0xffff); + + _interface->write_gpio(dboard_interface::GPIO_RX_BANK, 0x0000, 0xffff); //all zeros + _interface->write_gpio(dboard_interface::GPIO_TX_BANK, 0x0000, 0xffff); + + _interface->set_atr_reg(dboard_interface::GPIO_RX_BANK, 0x0000, 0x0000, 0x0000); //software controlled + _interface->set_atr_reg(dboard_interface::GPIO_TX_BANK, 0x0000, 0x0000, 0x0000); +} -- cgit v1.2.3 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 (limited to 'host/lib/usrp') 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 From 8050fda48d69f46788672a9ceaccd8d82500ac05 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 23 Feb 2010 16:27:49 -0800 Subject: Added IF data io handing within the usrp2 impl. It packs and unpacks vrt headers/metadata. NOT YET TESTED IN ANY WAY... --- host/include/uhd/CMakeLists.txt | 1 - host/include/uhd/device.hpp | 4 +- host/include/uhd/metadata.hpp | 4 + host/include/uhd/shared_iovec.hpp | 54 -------- host/include/uhd/transport/udp.hpp | 15 +-- host/lib/CMakeLists.txt | 2 +- host/lib/shared_iovec.cpp | 28 ---- host/lib/transport/udp.cpp | 20 +-- host/lib/usrp/usrp2/io_impl.cpp | 261 +++++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/usrp2_impl.cpp | 95 ++------------ host/lib/usrp/usrp2/usrp2_impl.hpp | 5 + 11 files changed, 299 insertions(+), 190 deletions(-) delete mode 100644 host/include/uhd/shared_iovec.hpp delete mode 100644 host/lib/shared_iovec.cpp create mode 100644 host/lib/usrp/usrp2/io_impl.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index e87f74291..f4fb96786 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -26,7 +26,6 @@ INSTALL(FILES gain_handler.hpp metadata.hpp props.hpp - shared_iovec.hpp time_spec.hpp utils.hpp wax.hpp diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index da58d4f85..596a98bc4 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -77,7 +77,7 @@ public: * \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 + * \return the number of samples sent */ virtual size_t send( const boost::asio::const_buffer &buff, @@ -91,7 +91,7 @@ public: * \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 + * \return the number of samples received */ virtual size_t recv( const boost::asio::mutable_buffer &buff, diff --git a/host/include/uhd/metadata.hpp b/host/include/uhd/metadata.hpp index 43b91d1b0..70842e7bc 100644 --- a/host/include/uhd/metadata.hpp +++ b/host/include/uhd/metadata.hpp @@ -30,13 +30,17 @@ namespace uhd{ */ struct metadata_t{ uint32_t stream_id; + bool has_stream_id; time_spec_t time_spec; + bool has_time_spec; bool start_of_burst; bool end_of_burst; metadata_t(void){ stream_id = 0; + has_stream_id = false; time_spec = time_spec_t(); + has_time_spec = false; start_of_burst = false; end_of_burst = false; } diff --git a/host/include/uhd/shared_iovec.hpp b/host/include/uhd/shared_iovec.hpp deleted file mode 100644 index a120e55d5..000000000 --- a/host/include/uhd/shared_iovec.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// 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_SHARED_IOVEC_HPP -#define INCLUDED_UHD_SHARED_IOVEC_HPP - -#include -#include - -namespace uhd{ - -/*! - * A shared iovec contains a shared array and its length. - * Creating a new shared iovec allocates new memory. - * This memory is freed when all copies are destroyed. - */ -class shared_iovec{ -public: - /*! - * Create a shared iovec and allocate memory. - * \param len the length in bytes - */ - shared_iovec(size_t len=0); - - /*! - * Destroy a shared iovec. - * Will not free the memory unless this is the last copy. - */ - ~shared_iovec(void); - - void *base; - size_t len; - -private: - boost::shared_array _shared_array; -}; - -} //namespace uhd - -#endif /* INCLUDED_UHD_SHARED_IOVEC_HPP */ diff --git a/host/include/uhd/transport/udp.hpp b/host/include/uhd/transport/udp.hpp index 07d84e62a..8c6fb096f 100644 --- a/host/include/uhd/transport/udp.hpp +++ b/host/include/uhd/transport/udp.hpp @@ -18,7 +18,6 @@ #include #include #include -#include #ifndef INCLUDED_UHD_TRANSPORT_UDP_HPP #define INCLUDED_UHD_TRANSPORT_UDP_HPP @@ -58,18 +57,18 @@ public: /*! * Receive a buffer. Write into the memory provided. * Returns empty when data is not available. - * \param buff a mutable buffer to receive into + * \param buffs a vector of asio buffers * \return the number of bytes received. */ - virtual size_t recv(const boost::asio::mutable_buffer &buff) = 0; + virtual size_t recv(const std::vector &buffs) = 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 + * 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 uhd::shared_iovec recv(void) = 0; + virtual size_t recv(const boost::asio::mutable_buffer &buff) = 0; }; }} //namespace diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 5cf334678..253f45614 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -20,7 +20,6 @@ SET(libuhd_sources device.cpp device_addr.cpp gain_handler.cpp - shared_iovec.cpp uhd.cpp wax.cpp transport/udp.cpp @@ -32,6 +31,7 @@ SET(libuhd_sources usrp/usrp2/dboard_impl.cpp usrp/usrp2/dboard_interface.cpp usrp/usrp2/dsp_impl.cpp + usrp/usrp2/io_impl.cpp usrp/usrp2/mboard_impl.cpp usrp/usrp2/usrp2_impl.cpp ) diff --git a/host/lib/shared_iovec.cpp b/host/lib/shared_iovec.cpp deleted file mode 100644 index 60062fbf0..000000000 --- a/host/lib/shared_iovec.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// 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 . -// - -#include - -uhd::shared_iovec::shared_iovec(size_t len_){ - _shared_array = boost::shared_array(new uint8_t[len_]); - base = _shared_array.get(); - len = len_; -} - -uhd::shared_iovec::~shared_iovec(void){ - /* NOP */ -} diff --git a/host/lib/transport/udp.cpp b/host/lib/transport/udp.cpp index fca4dd7d6..878f71410 100644 --- a/host/lib/transport/udp.cpp +++ b/host/lib/transport/udp.cpp @@ -31,8 +31,8 @@ public: //send/recv size_t send(const std::vector &buffs); size_t send(const boost::asio::const_buffer &buff); + size_t recv(const std::vector &buffs); size_t recv(const boost::asio::mutable_buffer &buff); - uhd::shared_iovec recv(void); private: boost::asio::ip::udp::socket *_socket; @@ -87,20 +87,12 @@ 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){ +size_t udp_impl::recv(const std::vector &buffs){ if (_socket->available() == 0) return 0; - return _socket->receive_from(boost::asio::buffer(buff), _sender_endpoint); + return _socket->receive_from(buffs, _sender_endpoint); } -uhd::shared_iovec udp_impl::recv(void){ - //allocate a buffer for the number of bytes available (could be zero) - uhd::shared_iovec iov(_socket->available()); - //call recv only if data is available - if (iov.len != 0){ - _socket->receive_from( - boost::asio::buffer(iov.base, iov.len), - _sender_endpoint - ); - } - return iov; +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); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp new file mode 100644 index 000000000..fbea71f85 --- /dev/null +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -0,0 +1,261 @@ +// +// 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 . +// + +#include +#include +#include +#include "usrp2_impl.hpp" + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Constants + **********************************************************************/ +typedef std::complex fc32_t; +typedef std::complex 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 void pack_vrt_header( + size_t num_data_words, //input + const uhd::metadata_t &metadata, //input + uint32_t *vrt_header, //output + size_t &vrt_header_words //output +){ + // +} + +static void unpack_vrt_header( + size_t &num_data_words, //output + uhd::metadata_t &metadata, //output + const uint32_t *vrt_header, //input + size_t &vrt_header_words //output +){ + // +}*/ + +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 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]++ << 16) & 0xf) | + ((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 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 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(raw_buff), + boost::asio::buffer_cast(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 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(raw_buff), + boost::asio::buffer_cast(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 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(buff), + boost::asio::buffer_cast(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 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(buff), + boost::asio::buffer_cast(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)); +} diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 47bf06aff..11e2f480b 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -44,19 +44,21 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ //loop and recieve until the time is up size_t num_timeouts = 0; while(true){ - uhd::shared_iovec iov = udp_transport->recv(); - //std::cout << boost::asio::buffer_size(buff) << "\n"; - if (iov.len < sizeof(usrp2_ctrl_data_t)){ + usrp2_ctrl_data_t ctrl_data_in; + size_t len = udp_transport->recv( + boost::asio::buffer(&ctrl_data_in, sizeof(ctrl_data_in)) + ); + //std::cout << len << "\n"; + if (len < sizeof(usrp2_ctrl_data_t)){ //sleep a little so we dont burn cpu if (num_timeouts++ > 50) break; boost::this_thread::sleep(boost::posix_time::milliseconds(1)); }else{ //handle the received data - const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast(iov.base); - switch(ntohl(ctrl_data_in->id)){ + switch(ntohl(ctrl_data_in.id)){ case USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE: //make a boost asio ipv4 with the raw addr in host byte order - boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.ip_addr)); + boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr)); device_addr_t new_addr; new_addr["name"] = "USRP2"; new_addr["type"] = "udp"; @@ -161,14 +163,16 @@ usrp2_ctrl_data_t usrp2_impl::ctrl_send_and_recv(const usrp2_ctrl_data_t &out_da //loop and recieve until the time is up size_t num_timeouts = 0; while(true){ - uhd::shared_iovec iov = _ctrl_transport->recv(); - if (iov.len < sizeof(usrp2_ctrl_data_t)){ + usrp2_ctrl_data_t in_data; + size_t len = _ctrl_transport->recv( + boost::asio::buffer(&in_data, sizeof(in_data)) + ); + if (len < sizeof(usrp2_ctrl_data_t)){ //sleep a little so we dont burn cpu if (num_timeouts++ > 50) break; boost::this_thread::sleep(boost::posix_time::milliseconds(1)); }else{ //handle the received data - usrp2_ctrl_data_t in_data = *reinterpret_cast(iov.base); if (ntohl(in_data.seq) == _ctrl_seq_num){ return in_data; } @@ -204,76 +208,3 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ void usrp2_impl::set(const wax::obj &, const wax::obj &){ throw std::runtime_error("Cannot set in usrp2 device"); } - -/*********************************************************************** - * IO Interface - **********************************************************************/ -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)); -} - -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 2476bcf1d..9a4c42d42 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -102,6 +102,11 @@ public: size_t recv(const boost::asio::mutable_buffer &, uhd::metadata_t &, const std::string &); private: + //the raw io interface (samples are in the usrp2 native format) + size_t send_raw(const boost::asio::const_buffer &, const uhd::metadata_t &); + size_t recv_raw(const boost::asio::mutable_buffer &, uhd::metadata_t &); + uhd::dict _stream_id_to_packet_seq; + //udp transports for control and data uhd::transport::udp::sptr _ctrl_transport; uhd::transport::udp::sptr _data_transport; -- cgit v1.2.3 From 588278f56766b0349115dec81d3fb714215c3774 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 23 Feb 2010 17:58:41 -0800 Subject: Put fast path code (rx setup) back into txrx.c. Store the fast path addrs in the udp data handler. --- firmware/microblaze/apps/txrx.c | 88 +++++++++++++++++++++++++++-------------- host/lib/usrp/usrp2/io_impl.cpp | 19 --------- 2 files changed, 59 insertions(+), 48 deletions(-) (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 16aa8eab2..1724284b0 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -47,6 +47,8 @@ #include #include #include +#include +#include #define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) @@ -136,10 +138,14 @@ static int streaming_frame_count = 0; bool is_streaming(void){ return streaming_p; } - // ---------------------------------------------------------------- +// the fast-path setup global variables +// ---------------------------------------------------------------- +static eth_mac_addr_t fp_mac_addr_src, fp_mac_addr_dst; +static struct socket_address fp_socket_src, fp_socket_dst; -void start_rx_streaming_cmd(void *p); +// ---------------------------------------------------------------- +void start_rx_streaming_cmd(void); void stop_rx_cmd(void); static eth_mac_addr_t get_my_eth_mac_addr(void){ @@ -158,11 +164,38 @@ void handle_udp_data_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ - //TODO store the reply port - //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); + if (payload_len > sizeof(uint32_t)){ + _is_data = true; + return; + } + + //its a tiny payload, load the fast-path variables + fp_mac_addr_src = get_my_eth_mac_addr(); + arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst); + fp_socket_src = dst; + fp_socket_dst = src; + printf("Storing for fast path:\n"); + printf(" source mac addr: "); + print_mac_addr(fp_mac_addr_src.addr); newline(); + printf(" source ip addr: %d.%d.%d.%d\n", + ((const unsigned char*)&fp_socket_src.addr.addr)[0], + ((const unsigned char*)&fp_socket_src.addr.addr)[1], + ((const unsigned char*)&fp_socket_src.addr.addr)[2], + ((const unsigned char*)&fp_socket_src.addr.addr)[3] + ); + printf(" source udp port: %d\n", fp_socket_src.port); + printf(" destination mac addr: "); + print_mac_addr(fp_mac_addr_dst.addr); newline(); + printf(" destination ip addr: %d.%d.%d.%d\n", + ((const unsigned char*)&fp_socket_dst.addr.addr)[0], + ((const unsigned char*)&fp_socket_dst.addr.addr)[1], + ((const unsigned char*)&fp_socket_dst.addr.addr)[2], + ((const unsigned char*)&fp_socket_dst.addr.addr)[3] + ); + printf(" destination udp port: %d\n", fp_socket_dst.port); + newline(); } #define OTW_GPIO_BANK_TO_NUM(bank) \ @@ -426,7 +459,7 @@ void handle_udp_ctrl_packet( stop_rx_cmd(); } else{ - start_rx_streaming_cmd(NULL); + start_rx_streaming_cmd(); } ctrl_data_out.id = USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE; @@ -483,7 +516,7 @@ eth_pkt_inspector(dbsm_t *sm, int bufno) //------------------------------------------------------------------ #define VRT_HEADER_WORDS 5 -#define VRT_TRAILER_WORDS 1 +#define VRT_TRAILER_WORDS 0 void restart_streaming(void) @@ -494,7 +527,7 @@ restart_streaming(void) sr_rx_ctrl->clear_overrun = 1; // reset sr_rx_ctrl->vrt_header = (0 | VRTH_PT_IF_DATA_WITH_SID - | VRTH_HAS_TRAILER + | ((VRT_TRAILER_WORDS)? VRTH_HAS_TRAILER : 0) | VRTH_TSI_OTHER | VRTH_TSF_SAMPLE_CNT | (VRT_HEADER_WORDS+streaming_items_per_frame+VRT_TRAILER_WORDS)); @@ -527,14 +560,14 @@ restart_streaming(void) * * init chksum to zero to start. */ -/*static unsigned int +static unsigned int CHKSUM(unsigned int x, unsigned int *chksum) { *chksum += x; *chksum = (*chksum & 0xffff) + (*chksum>>16); *chksum = (*chksum & 0xffff) + (*chksum>>16); return x; -}*/ +} /* * Called when eth phy state changes (w/ interrupts disabled) @@ -549,7 +582,7 @@ link_changed_callback(int speed) } void -start_rx_streaming_cmd(void *p) +start_rx_streaming_cmd(void) { /* * Construct ethernet header and preload into two buffers @@ -559,31 +592,31 @@ start_rx_streaming_cmd(void *p) } mem _AL4; memset(&mem, 0, sizeof(mem)); - //p->items_per_frame = (1500)/sizeof(uint32_t) - (DSP_TX_FIRST_LINE + VRT_HEADER_WORDS + VRT_TRAILER_WORDS); //FIXME - //mem.ctrl_word = (VRT_HEADER_WORDS+p->items_per_frame+VRT_TRAILER_WORDS)*sizeof(uint32_t) | 1 << 16; + streaming_items_per_frame = (1500)/sizeof(uint32_t) - (DSP_TX_FIRST_LINE + VRT_HEADER_WORDS + VRT_TRAILER_WORDS); //FIXME + mem.ctrl_word = (VRT_HEADER_WORDS+streaming_items_per_frame+VRT_TRAILER_WORDS)*sizeof(uint32_t) | 1 << 16; memcpy_wa(buffer_ram(DSP_RX_BUF_0), &mem, sizeof(mem)); memcpy_wa(buffer_ram(DSP_RX_BUF_1), &mem, sizeof(mem)); //setup ethernet header machine - /*sr_udp_sm->eth_hdr.mac_dst_0_1 = (host_dst_mac_addr.addr[0] << 8) | host_dst_mac_addr.addr[1]; - sr_udp_sm->eth_hdr.mac_dst_2_3 = (host_dst_mac_addr.addr[2] << 8) | host_dst_mac_addr.addr[3]; - sr_udp_sm->eth_hdr.mac_dst_4_5 = (host_dst_mac_addr.addr[4] << 8) | host_dst_mac_addr.addr[5]; - sr_udp_sm->eth_hdr.mac_src_0_1 = (host_src_mac_addr.addr[0] << 8) | host_src_mac_addr.addr[1]; - sr_udp_sm->eth_hdr.mac_src_2_3 = (host_src_mac_addr.addr[2] << 8) | host_src_mac_addr.addr[3]; - sr_udp_sm->eth_hdr.mac_src_4_5 = (host_src_mac_addr.addr[4] << 8) | host_src_mac_addr.addr[5]; - sr_udp_sm->eth_hdr.ether_type = ETHERTYPE_IPV4;*/ + sr_udp_sm->eth_hdr.mac_dst_0_1 = (fp_mac_addr_dst.addr[0] << 8) | fp_mac_addr_dst.addr[1]; + sr_udp_sm->eth_hdr.mac_dst_2_3 = (fp_mac_addr_dst.addr[2] << 8) | fp_mac_addr_dst.addr[3]; + sr_udp_sm->eth_hdr.mac_dst_4_5 = (fp_mac_addr_dst.addr[4] << 8) | fp_mac_addr_dst.addr[5]; + sr_udp_sm->eth_hdr.mac_src_0_1 = (fp_mac_addr_src.addr[0] << 8) | fp_mac_addr_src.addr[1]; + sr_udp_sm->eth_hdr.mac_src_2_3 = (fp_mac_addr_src.addr[2] << 8) | fp_mac_addr_src.addr[3]; + sr_udp_sm->eth_hdr.mac_src_4_5 = (fp_mac_addr_src.addr[4] << 8) | fp_mac_addr_src.addr[5]; + sr_udp_sm->eth_hdr.ether_type = ETHERTYPE_IPV4; //setup ip header machine - /*unsigned int chksum = 0; + unsigned int chksum = 0; sr_udp_sm->ip_hdr.ver_ihl_tos = CHKSUM(0x4500, &chksum); // IPV4, 5 words of header (20 bytes), TOS=0 sr_udp_sm->ip_hdr.total_length = UDP_SM_INS_IP_LEN; // Don't checksum this line in SW sr_udp_sm->ip_hdr.identification = CHKSUM(0x0000, &chksum); // ID sr_udp_sm->ip_hdr.flags_frag_off = CHKSUM(0x4000, &chksum); // don't fragment sr_udp_sm->ip_hdr.ttl_proto = CHKSUM(0x2011, &chksum); // TTL=32, protocol = UDP (17 decimal) //sr_udp_sm->ip_hdr.checksum .... filled in below - uint32_t src_ip_addr = host_src_ip_addr.s_addr; - uint32_t dst_ip_addr = host_dst_ip_addr.s_addr; + uint32_t src_ip_addr = fp_socket_src.addr.addr; + uint32_t dst_ip_addr = fp_socket_dst.addr.addr; sr_udp_sm->ip_hdr.src_addr_high = CHKSUM(src_ip_addr >> 16, &chksum); // IP src high sr_udp_sm->ip_hdr.src_addr_low = CHKSUM(src_ip_addr & 0xffff, &chksum); // IP src low sr_udp_sm->ip_hdr.dst_addr_high = CHKSUM(dst_ip_addr >> 16, &chksum); // IP dst high @@ -591,17 +624,14 @@ start_rx_streaming_cmd(void *p) sr_udp_sm->ip_hdr.checksum = UDP_SM_INS_IP_HDR_CHKSUM | (chksum & 0xffff); //setup the udp header machine - sr_udp_sm->udp_hdr.src_port = host_src_udp_port; - sr_udp_sm->udp_hdr.dst_port = host_dst_udp_port; + sr_udp_sm->udp_hdr.src_port = fp_socket_src.port; + sr_udp_sm->udp_hdr.dst_port = fp_socket_dst.port; sr_udp_sm->udp_hdr.length = UDP_SM_INS_UDP_LEN; - sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum*/ + sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum if (FW_SETS_SEQNO) fw_seqno = 0; - //streaming_items_per_frame = p->items_per_frame; - //time_secs = p->time_secs; - //time_ticks = p->time_ticks; restart_streaming(); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index fbea71f85..4781036ea 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -37,25 +37,6 @@ static const size_t max_vrt_header_words = 5; /*********************************************************************** * Helper Functions **********************************************************************/ - -/*static void pack_vrt_header( - size_t num_data_words, //input - const uhd::metadata_t &metadata, //input - uint32_t *vrt_header, //output - size_t &vrt_header_words //output -){ - // -} - -static void unpack_vrt_header( - size_t &num_data_words, //output - uhd::metadata_t &metadata, //output - const uint32_t *vrt_header, //input - size_t &vrt_header_words //output -){ - // -}*/ - static inline void host_floats_to_usrp2_shorts( int16_t *usrp2_shorts, const float *host_floats, -- cgit v1.2.3 From c12d6d0f5f2bbfd749b5a18b167ed7a485cd03a1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 23 Feb 2010 18:16:34 -0800 Subject: vrt packet count fix --- host/lib/usrp/usrp2/io_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 4781036ea..43334ddc6 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -105,7 +105,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]++ << 16) & 0xf) | + ((_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) | ((boost::asio::buffer_size(buff)/sizeof(uint32_t)) & 0xffff) ); -- cgit v1.2.3 From a9f8ba6e37e1349ce61b5022ddaff1c64dd52bd3 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Feb 2010 18:26:00 +0000 Subject: added usrp1e conditional compilation, and checking of device node (aka file for now) --- host/lib/CMakeLists.txt | 14 ++++++-- host/lib/usrp/usrp1e/usrp1e_impl.cpp | 69 ++++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp1e/usrp1e_impl.hpp | 23 ++++++++++++ host/lib/usrp/usrp2/usrp2_impl.cpp | 1 - 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 host/lib/usrp/usrp1e/usrp1e_impl.cpp create mode 100644 host/lib/usrp/usrp1e/usrp1e_impl.hpp (limited to 'host/lib/usrp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index edfefa127..96fba6e53 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -41,9 +41,17 @@ SET(libuhd_sources ######################################################################## # Conditionally add the usrp1e sources ######################################################################## -LIST(APPEND libuhd_sources - usrp/usrp1e/usrp1e_none.cpp -) +INCLUDE(CheckIncludeFile) +CHECK_INCLUDE_FILE("linux/ioctl.h" HAS_LINUX_IOCTL_H) +IF(HAS_LINUX_IOCTL_H) + LIST(APPEND libuhd_sources + usrp/usrp1e/usrp1e_impl.cpp + ) +ELSE(HAS_LINUX_IOCTL_H) + LIST(APPEND libuhd_sources + usrp/usrp1e/usrp1e_none.cpp + ) +ENDIF(HAS_LINUX_IOCTL_H) ######################################################################## # Setup libuhd library diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.cpp b/host/lib/usrp/usrp1e/usrp1e_impl.cpp new file mode 100644 index 000000000..93265ab17 --- /dev/null +++ b/host/lib/usrp/usrp1e/usrp1e_impl.cpp @@ -0,0 +1,69 @@ +// +// 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 . +// + +#include +#include +#include "usrp1e_impl.hpp" + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +static bool file_exists(const std::string &file_path){ + return access(file_path.c_str(), F_OK) == 0; +} + +/*********************************************************************** + * Discovery + **********************************************************************/ +device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ + device_addrs_t usrp1e_addrs; + + //if a node was provided, use it and only it + if (device_addr.has_key("node")){ + if (not file_exists(device_addr["node"])) return usrp1e_addrs; + device_addr_t new_addr; + new_addr["name"] = "USRP1E"; + new_addr["type"] = "usrp1e"; + new_addr["node"] = device_addr["node"]; + usrp1e_addrs.push_back(new_addr); + } + + //otherwise look for a few nodes at small indexes + else{ + for(size_t i = 0; i < 5; i++){ + std::string node = str(boost::format("/dev/usrp1_e%d") % i); + if (not file_exists(node)) continue; + device_addr_t new_addr; + new_addr["name"] = "USRP1E"; + new_addr["type"] = "usrp1e"; + new_addr["node"] = node; + usrp1e_addrs.push_back(new_addr); + } + } + + return usrp1e_addrs; +} + +/*********************************************************************** + * Make + **********************************************************************/ +device::sptr usrp1e::make(const device_addr_t &){ + throw std::runtime_error("not implemented yet"); +} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.hpp b/host/lib/usrp/usrp1e/usrp1e_impl.hpp new file mode 100644 index 000000000..3f5f89ec6 --- /dev/null +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -0,0 +1,23 @@ +// +// 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 . +// + +#include + +#ifndef INCLUDED_USRP1E_IMPL_HPP +#define INCLUDED_USRP1E_IMPL_HPP + +#endif /* INCLUDED_USRP1E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 06876d241..5aa5d6e8d 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -62,7 +62,6 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ device_addr_t new_addr; new_addr["name"] = "USRP2"; new_addr["type"] = "usrp2"; - new_addr["transport"] = "udp"; new_addr["addr"] = ip_addr.to_string(); usrp2_addrs.push_back(new_addr); break; -- cgit v1.2.3 From 778a41b393b7d517463950c4ac014d3a2eb8eceb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Feb 2010 19:43:20 +0000 Subject: added usrp1e fpga loader --- host/include/uhd/usrp/usrp1e.hpp | 6 + host/lib/CMakeLists.txt | 21 ++- host/lib/usrp/usrp1e/fpga-downloader.cc | 262 ++++++++++++++++++++++++++++++++ host/lib/usrp/usrp1e/usrp1e_none.cpp | 4 + 4 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 host/lib/usrp/usrp1e/fpga-downloader.cc (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/usrp1e.hpp b/host/include/uhd/usrp/usrp1e.hpp index 00748e55f..60a6a191a 100644 --- a/host/include/uhd/usrp/usrp1e.hpp +++ b/host/include/uhd/usrp/usrp1e.hpp @@ -41,6 +41,12 @@ public: * \return a device sptr to a new usrp1e */ static device::sptr make(const device_addr_t &addr); + + /*! + * Load the FPGA with an image file. + * \param bin_file the name of the fpga image file + */ + static void load_fpga(const std::string &bin_file); }; }} //namespace diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 96fba6e53..33314e729 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -41,17 +41,28 @@ SET(libuhd_sources ######################################################################## # Conditionally add the usrp1e sources ######################################################################## -INCLUDE(CheckIncludeFile) -CHECK_INCLUDE_FILE("linux/ioctl.h" HAS_LINUX_IOCTL_H) -IF(HAS_LINUX_IOCTL_H) +INCLUDE(CheckIncludeFiles) +SET(usrp1e_required_headers + linux/ioctl.h + linux/spi/spidev.h +) +CHECK_INCLUDE_FILES( + "${usrp1e_required_headers}" + HAS_USRP1E_REQUIRED_HEADERS +) + +IF(HAS_USRP1E_REQUIRED_HEADERS) + MESSAGE(STATUS "Building usrp1e support...") LIST(APPEND libuhd_sources + usrp/usrp1e/fpga-downloader.cc usrp/usrp1e/usrp1e_impl.cpp ) -ELSE(HAS_LINUX_IOCTL_H) +ELSE(HAS_USRP1E_REQUIRED_HEADERS) + MESSAGE(STATUS "Skipping usrp1e support...") LIST(APPEND libuhd_sources usrp/usrp1e/usrp1e_none.cpp ) -ENDIF(HAS_LINUX_IOCTL_H) +ENDIF(HAS_USRP1E_REQUIRED_HEADERS) ######################################################################## # Setup libuhd library diff --git a/host/lib/usrp/usrp1e/fpga-downloader.cc b/host/lib/usrp/usrp1e/fpga-downloader.cc new file mode 100644 index 000000000..15023d945 --- /dev/null +++ b/host/lib/usrp/usrp1e/fpga-downloader.cc @@ -0,0 +1,262 @@ +// +// 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 . +// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * Configuration connections + * + * CCK - MCSPI1_CLK + * DIN - MCSPI1_MOSI + * PROG_B - GPIO_175 - output (change mux) + * DONE - GPIO_173 - input (change mux) + * INIT_B - GPIO_114 - input (change mux) + * +*/ + +const unsigned int PROG_B = 175; +const unsigned int DONE = 173; +const unsigned int INIT_B = 114; + +static std::string bit_file = "safe_u1e.bin"; + +const int BUF_SIZE = 4096; + +enum gpio_direction {IN, OUT}; + +class gpio { + public: + + gpio(unsigned int gpio_num, gpio_direction pin_direction); + + bool get_value(); + void set_value(bool state); + + private: + + std::stringstream base_path; + std::fstream value_file; +}; + +class spidev { + public: + + spidev(std::string dev_name); + ~spidev(); + + void send(char *wbuf, char *rbuf, unsigned int nbytes); + + private: + + int fd; + +}; + +gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) +{ + std::fstream export_file; + + export_file.open("/sys/class/gpio/export", std::ios::out); + if (!export_file.is_open()) ///\todo Poor error handling + std::cout << "Failed to open gpio export file." << std::endl; + + export_file << gpio_num << std::endl; + + base_path << "/sys/class/gpio/gpio" << gpio_num << std::flush; + + std::fstream direction_file; + std::string direction_file_name; + + direction_file_name = base_path.str() + "/direction"; + + direction_file.open(direction_file_name.c_str()); + if (!direction_file.is_open()) + std::cout << "Failed to open direction file." << std::endl; + if (pin_direction == OUT) + direction_file << "out" << std::endl; + else + direction_file << "in" << std::endl; + + std::string value_file_name; + + value_file_name = base_path.str() + "/value"; + + value_file.open(value_file_name.c_str(), std::ios_base::in | std::ios_base::out); + if (!value_file.is_open()) + std::cout << "Failed to open value file." << std::endl; +} + +bool gpio::get_value() +{ + + std::string val; + + std::getline(value_file, val); + value_file.seekg(0); + + if (val == "0") + return false; + else if (val == "1") + return true; + else + std::cout << "Data read from value file|" << val << "|" << std::endl; + + return false; +} + +void gpio::set_value(bool state) +{ + + if (state) + value_file << "1" << std::endl; + else + value_file << "0" << std::endl; +} + +static void prepare_fpga_for_configuration(gpio &prog, gpio &)//init) +{ + + prog.set_value(true); + prog.set_value(false); + prog.set_value(true); + +#if 0 + bool ready_to_program(false); + unsigned int count(0); + do { + ready_to_program = init.get_value(); + count++; + + sleep(1); + } while (count < 10 && !ready_to_program); + + if (count == 10) { + std::cout << "FPGA not ready for programming." << std::endl; + exit(-1); + } +#endif +} + +spidev::spidev(std::string fname) +{ + int ret; + int mode = 0; + int speed = 12000000; + int bits = 8; + + fd = open(fname.c_str(), O_RDWR); + + ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); + ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); +} + + +spidev::~spidev() +{ + close(fd); +} + +void spidev::send(char *buf, char *rbuf, unsigned int nbytes) +{ + int ret; + + struct spi_ioc_transfer tr; + tr.tx_buf = (unsigned long) buf; + tr.rx_buf = (unsigned long) rbuf; + tr.len = nbytes; + tr.delay_usecs = 0; + tr.speed_hz = 48000000; + tr.bits_per_word = 8; + + ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); + +} + +static void send_file_to_fpga(std::string &file_name, gpio &error, gpio &done) +{ + std::ifstream bitstream; + + std::cout << "File name - " << file_name.c_str() << std::endl; + + bitstream.open(file_name.c_str(), std::ios::binary); + if (!bitstream.is_open()) + std::cout << "File " << file_name << " not opened succesfully." << std::endl; + + spidev spi("/dev/spidev1.0"); + char buf[BUF_SIZE]; + char rbuf[BUF_SIZE]; + + do { + bitstream.read(buf, BUF_SIZE); + spi.send(buf, rbuf, bitstream.gcount()); + + if (error.get_value()) + std::cout << "INIT_B went high, error occured." << std::endl; + + if (!done.get_value()) + std::cout << "Configuration complete." << std::endl; + + } while (bitstream.gcount() == BUF_SIZE); +} + +/* +int main(int argc, char *argv[]) +{ + + gpio gpio_prog_b(PROG_B, OUT); + gpio gpio_init_b(INIT_B, IN); + gpio gpio_done (DONE, IN); + + if (argc == 2) + bit_file = argv[1]; + + std::cout << "FPGA config file: " << bit_file << std::endl; + + prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); + + std::cout << "Done = " << gpio_done.get_value() << std::endl; + + send_file_to_fpga(bit_file, gpio_init_b, gpio_done); +} +*/ + +#include +void uhd::usrp::usrp1e::load_fpga(const std::string &bin_file){ + gpio gpio_prog_b(PROG_B, OUT); + gpio gpio_init_b(INIT_B, IN); + gpio gpio_done (DONE, IN); + + std::cout << "FPGA config file: " << bin_file << std::endl; + + prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); + + std::cout << "Done = " << gpio_done.get_value() << std::endl; + + send_file_to_fpga(bit_file, gpio_init_b, gpio_done); +} diff --git a/host/lib/usrp/usrp1e/usrp1e_none.cpp b/host/lib/usrp/usrp1e/usrp1e_none.cpp index 1c8cf9a5b..ac0b12a75 100644 --- a/host/lib/usrp/usrp1e/usrp1e_none.cpp +++ b/host/lib/usrp/usrp1e/usrp1e_none.cpp @@ -32,3 +32,7 @@ device_addrs_t usrp1e::discover(const device_addr_t &){ device::sptr usrp1e::make(const device_addr_t &){ throw std::runtime_error("this build has no usrp1e support"); } + +void usrp1e::load_fpga(const std::string &){ + throw std::runtime_error("this build has no usrp1e support"); +} -- cgit v1.2.3 From 3571f65a1184dd65be39bc19708cc316fd017497 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Feb 2010 12:48:51 -0800 Subject: use a single addr param for the usrp2 --- host/apps/discover_usrps.cpp | 14 ++++++-------- host/lib/device.cpp | 7 ++----- host/lib/usrp/usrp2/usrp2_impl.cpp | 4 ++-- 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/apps/discover_usrps.cpp b/host/apps/discover_usrps.cpp index 02c05b7cc..08135a27c 100644 --- a/host/apps/discover_usrps.cpp +++ b/host/apps/discover_usrps.cpp @@ -22,13 +22,12 @@ #include namespace po = boost::program_options; -using namespace uhd; int main(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("ip-addr", po::value(), "usrp2 ip address") + ("addr", po::value(), "resolvable network address") ; po::variables_map vm; @@ -41,13 +40,12 @@ int main(int argc, char *argv[]){ return ~0; } - //extract the ip address (not optional for now) + //extract the address (not optional for now) uhd::device_addr_t device_addr; - device_addr["type"] = "udp"; - if (vm.count("ip-addr")) { - device_addr["addr"] = vm["ip-addr"].as(); + if (vm.count("addr")) { + device_addr["addr"] = vm["addr"].as(); } else { - std::cout << "IP Addess was not set" << std::endl; + std::cout << "The address was not set" << std::endl; return ~0; } @@ -59,7 +57,7 @@ int main(int argc, char *argv[]){ std::cout << "--------------------------------------------------" << std::endl; std::cout << device_addrs[i] << std::endl << std::endl; //make each device just to test (TODO: remove this) - uhd::device::sptr dev = device::make(device_addrs[i]); + uhd::device::sptr dev = uhd::device::make(device_addrs[i]); std::cout << wax::cast((*dev)[uhd::DEVICE_PROP_MBOARD][uhd::MBOARD_PROP_NAME]) << std::endl; } diff --git a/host/lib/device.cpp b/host/lib/device.cpp index e376a5c50..f181d31e4 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -24,10 +24,7 @@ using namespace uhd; device_addrs_t device::discover(const device_addr_t &hint){ device_addrs_t device_addrs; - if (not hint.has_key("type")){ - //TODO call discover for others and append results - } - else if (hint["type"] == "udp"){ + if (hint.has_key("addr")){ std::vector usrp2_addrs = usrp::usrp2::discover(hint); device_addrs.insert(device_addrs.begin(), usrp2_addrs.begin(), usrp2_addrs.end()); } @@ -53,7 +50,7 @@ device::sptr device::make(const device_addr_t &hint, size_t which){ //create the new device with the discovered address //TODO only a usrp2 device will be made (until others are supported) - if (hint.has_key("type") and hint["type"] == "udp"){ + if (hint.has_key("addr")){ return usrp::usrp2::make(device_addrs.at(which)); } throw std::runtime_error("cant make a device"); diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 11e2f480b..770fa3e53 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -60,8 +60,8 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ //make a boost asio ipv4 with the raw addr in host byte order boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr)); device_addr_t new_addr; - new_addr["name"] = "USRP2"; - new_addr["type"] = "udp"; + new_addr["name"] = "usrp2"; + new_addr["transport"] = "udp"; new_addr["addr"] = ip_addr.to_string(); usrp2_addrs.push_back(new_addr); break; -- cgit v1.2.3 From 5715b2c4937ca094ca8f1d9d9b55c4edcc959981 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Feb 2010 18:32:32 -0800 Subject: Created empty usrp1e cpp file for the case when headers are not found. Worked on the device make and discovery to fix certain problems. Added node param to discover usrps for usrp1e, made addr optional. --- host/apps/discover_usrps.cpp | 21 +++++--- host/include/uhd/device.hpp | 4 -- host/include/uhd/device_addr.hpp | 4 +- host/include/uhd/usrp/CMakeLists.txt | 1 + host/include/uhd/usrp/usrp1e.hpp | 48 +++++++++++++++++ host/include/uhd/usrp/usrp2.hpp | 6 +-- host/lib/CMakeLists.txt | 14 ++++- host/lib/device.cpp | 100 +++++++++++++++++++++++++++++------ host/lib/device_addr.cpp | 4 +- host/lib/usrp/usrp1e/usrp1e_none.cpp | 34 ++++++++++++ host/lib/usrp/usrp2/usrp2_impl.cpp | 3 +- 11 files changed, 204 insertions(+), 35 deletions(-) create mode 100644 host/include/uhd/usrp/usrp1e.hpp create mode 100644 host/lib/usrp/usrp1e/usrp1e_none.cpp (limited to 'host/lib/usrp') diff --git a/host/apps/discover_usrps.cpp b/host/apps/discover_usrps.cpp index 08135a27c..7e8c21673 100644 --- a/host/apps/discover_usrps.cpp +++ b/host/apps/discover_usrps.cpp @@ -28,6 +28,7 @@ int main(int argc, char *argv[]){ desc.add_options() ("help", "help message") ("addr", po::value(), "resolvable network address") + ("node", po::value(), "path to linux device node") ; po::variables_map vm; @@ -35,22 +36,28 @@ int main(int argc, char *argv[]){ po::notify(vm); //print the help message - if (vm.count("help")) { + if (vm.count("help")){ std::cout << boost::format("Discover USRPs %s") % desc << std::endl; return ~0; } - //extract the address (not optional for now) + //load the options into the address uhd::device_addr_t device_addr; - if (vm.count("addr")) { + if (vm.count("addr")){ device_addr["addr"] = vm["addr"].as(); - } else { - std::cout << "The address was not set" << std::endl; + } + if (vm.count("node")){ + device_addr["node"] = vm["node"].as(); + } + + //discover the usrps and print the results + uhd::device_addrs_t device_addrs = uhd::device::discover(device_addr); + + if (device_addrs.size() == 0){ + std::cerr << "No USRP Devices Found" << std::endl; return ~0; } - //discover the usrps - std::vector device_addrs = uhd::device::discover(device_addr); for (size_t i = 0; i < device_addrs.size(); i++){ std::cout << "--------------------------------------------------" << std::endl; std::cout << "-- USRP Device " << i << std::endl; diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 596a98bc4..ba5337d33 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -38,10 +38,6 @@ class device : boost::noncopyable, public wax::obj{ public: typedef boost::shared_ptr sptr; - //structors - device(void); - virtual ~device(void); - /*! * \brief Discover usrp devices attached to the host. * diff --git a/host/include/uhd/device_addr.hpp b/host/include/uhd/device_addr.hpp index 8ea580321..d02febd6c 100644 --- a/host/include/uhd/device_addr.hpp +++ b/host/include/uhd/device_addr.hpp @@ -56,7 +56,9 @@ namespace uhd{ * \param device_addr a device address instance * \return the string representation */ - std::string device_addr_to_string(const device_addr_t &device_addr); + struct device_addr{ + static std::string to_string(const device_addr_t &device_addr); + }; } //namespace uhd diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index e7bdc1784..4e0a92365 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -21,6 +21,7 @@ INSTALL(FILES dboard_id.hpp dboard_interface.hpp dboard_manager.hpp + usrp1e.hpp usrp2.hpp DESTINATION ${HEADER_DIR}/uhd/usrp ) diff --git a/host/include/uhd/usrp/usrp1e.hpp b/host/include/uhd/usrp/usrp1e.hpp new file mode 100644 index 000000000..00748e55f --- /dev/null +++ b/host/include/uhd/usrp/usrp1e.hpp @@ -0,0 +1,48 @@ +// +// 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_USRP_USRP1E_HPP +#define INCLUDED_UHD_USRP_USRP1E_HPP + +#include + +namespace uhd{ namespace usrp{ + +/*! + * The usrp1e device class. + */ +class usrp1e : public device{ +public: + /*! + * Discover usrp1e devices on the system via the device node. + * This static method will be called by the device::discover. + * \param hint a device addr with the usrp1e address filled in + * \return a vector of device addresses for all usrp1es found + */ + static device_addrs_t discover(const device_addr_t &hint); + + /*! + * Make a usrp1e from a device address. + * \param addr the device address + * \return a device sptr to a new usrp1e + */ + static device::sptr make(const device_addr_t &addr); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_USRP1E_HPP */ diff --git a/host/include/uhd/usrp/usrp2.hpp b/host/include/uhd/usrp/usrp2.hpp index f6e49cbd6..da7ec595a 100644 --- a/host/include/uhd/usrp/usrp2.hpp +++ b/host/include/uhd/usrp/usrp2.hpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#ifndef INCLUDED_UHD_USRP_MBOARD_USRP2_HPP -#define INCLUDED_UHD_USRP_MBOARD_USRP2_HPP +#ifndef INCLUDED_UHD_USRP_USRP2_HPP +#define INCLUDED_UHD_USRP_USRP2_HPP #include @@ -45,4 +45,4 @@ public: }} //namespace -#endif /* INCLUDED_UHD_USRP_MBOARD_USRP2_HPP */ +#endif /* INCLUDED_UHD_USRP_USRP2_HPP */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 253f45614..edfefa127 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -15,7 +15,9 @@ # along with this program. If not, see . # - +######################################################################## +# Create a list of libuhd sources +######################################################################## SET(libuhd_sources device.cpp device_addr.cpp @@ -36,6 +38,16 @@ SET(libuhd_sources usrp/usrp2/usrp2_impl.cpp ) +######################################################################## +# Conditionally add the usrp1e sources +######################################################################## +LIST(APPEND libuhd_sources + usrp/usrp1e/usrp1e_none.cpp +) + +######################################################################## +# Setup libuhd library +######################################################################## ADD_LIBRARY(uhd SHARED ${libuhd_sources}) TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES}) diff --git a/host/lib/device.cpp b/host/lib/device.cpp index f181d31e4..82052708a 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -12,54 +12,122 @@ // 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 . +// asize_t with this program. If not, see . // +#include #include -#include +#include +#include +#include #include +#include +#include #include +#include using namespace uhd; +/*! + * Create a new device from a device address. + * Based on the address, call the appropriate make functions. + * \param dev_addr the device address + * \return a smart pointer to a device + */ +static device::sptr make_device(const device_addr_t &dev_addr){ + + //create a usrp1e + if (dev_addr["type"] == "usrp1e"){ + return usrp::usrp1e::make(dev_addr); + } + + //create a usrp2 + if (dev_addr["type"] == "usrp2"){ + return usrp::usrp2::make(dev_addr); + } + + throw std::runtime_error("cant make a device"); +} + +/*! + * Make a device hash that maps 1 to 1 with a device address. + * The hash will be used to identify created devices. + * \param dev_addr the device address + * \return the hash number + */ +static size_t hash_device_addr( + const device_addr_t &dev_addr +){ + //sort the keys of the device address + std::vector keys = dev_addr.get_keys(); + std::sort(keys.begin(), keys.end()); + + //combine the hashes of sorted keys/value pairs + size_t hash = 0; + BOOST_FOREACH(std::string key, keys){ + boost::hash_combine(hash, key); + boost::hash_combine(hash, dev_addr[key]); + } + return hash; +} + +/*********************************************************************** + * Discover + **********************************************************************/ device_addrs_t device::discover(const device_addr_t &hint){ device_addrs_t device_addrs; + + //discover the usrp1es + std::vector usrp2_addrs = usrp::usrp1e::discover(hint); + device_addrs.insert(device_addrs.begin(), usrp2_addrs.begin(), usrp2_addrs.end()); + + //discover the usrp2s if (hint.has_key("addr")){ std::vector usrp2_addrs = usrp::usrp2::discover(hint); device_addrs.insert(device_addrs.begin(), usrp2_addrs.begin(), usrp2_addrs.end()); } + return device_addrs; } +/*********************************************************************** + * Make + **********************************************************************/ device::sptr device::make(const device_addr_t &hint, size_t which){ std::vector device_addrs = discover(hint); //check that we found any devices if (device_addrs.size() == 0){ throw std::runtime_error(str( - boost::format("No devices found for %s") % device_addr_to_string(hint) + boost::format("No devices found for %s") % device_addr::to_string(hint) )); } //check that the which index is valid if (device_addrs.size() <= which){ throw std::runtime_error(str( - boost::format("No device at index %d for %s") % which % device_addr_to_string(hint) + boost::format("No device at index %d for %s") % which % device_addr::to_string(hint) )); } - //create the new device with the discovered address - //TODO only a usrp2 device will be made (until others are supported) - if (hint.has_key("addr")){ - return usrp::usrp2::make(device_addrs.at(which)); - } - throw std::runtime_error("cant make a device"); -} + //create a unique hash for the device address + device_addr_t dev_addr = device_addrs.at(which); + size_t dev_hash = hash_device_addr(dev_addr); + //std::cout << boost::format("Hash: %u") % dev_hash << std::endl; -device::device(void){ - /* NOP */ -} + //map device address hash to created devices + static uhd::dict > hash_to_device; -device::~device(void){ - /* NOP */ + //try to find an existing device + try{ + ASSERT_THROW(hash_to_device.has_key(dev_hash)); + ASSERT_THROW(not hash_to_device[dev_hash].expired()); + return hash_to_device[dev_hash].lock(); + } + //create and register a new device + catch(const std::assert_error &e){ + device::sptr dev = make_device(dev_addr); + hash_to_device[dev_hash] = dev; + return dev; + } } diff --git a/host/lib/device_addr.cpp b/host/lib/device_addr.cpp index ffd511f92..9514df981 100644 --- a/host/lib/device_addr.cpp +++ b/host/lib/device_addr.cpp @@ -72,7 +72,7 @@ std::ostream& operator<<(std::ostream &os, const uhd::mac_addr_t &x){ } //----------------------- usrp device_addr_t wrapper -------------------------// -std::string uhd::device_addr_to_string(const uhd::device_addr_t &device_addr){ +std::string uhd::device_addr::to_string(const uhd::device_addr_t &device_addr){ std::stringstream ss; BOOST_FOREACH(std::string key, device_addr.get_keys()){ ss << boost::format("%s: %s") % key % device_addr[key] << std::endl; @@ -81,6 +81,6 @@ std::string uhd::device_addr_to_string(const uhd::device_addr_t &device_addr){ } std::ostream& operator<<(std::ostream &os, const uhd::device_addr_t &device_addr){ - os << uhd::device_addr_to_string(device_addr); + os << uhd::device_addr::to_string(device_addr); return os; } diff --git a/host/lib/usrp/usrp1e/usrp1e_none.cpp b/host/lib/usrp/usrp1e/usrp1e_none.cpp new file mode 100644 index 000000000..1c8cf9a5b --- /dev/null +++ b/host/lib/usrp/usrp1e/usrp1e_none.cpp @@ -0,0 +1,34 @@ +// +// 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 . +// + +#include + +using namespace uhd; +using namespace uhd::usrp; + +/*! + * This file defines the usrp1e discover and make functions + * when the required kernel module headers are not present. + */ + +device_addrs_t usrp1e::discover(const device_addr_t &){ + return device_addrs_t(); //return empty list +} + +device::sptr usrp1e::make(const device_addr_t &){ + throw std::runtime_error("this build has no usrp1e support"); +} diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 770fa3e53..06876d241 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -60,7 +60,8 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ //make a boost asio ipv4 with the raw addr in host byte order boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr)); device_addr_t new_addr; - new_addr["name"] = "usrp2"; + new_addr["name"] = "USRP2"; + new_addr["type"] = "usrp2"; new_addr["transport"] = "udp"; new_addr["addr"] = ip_addr.to_string(); usrp2_addrs.push_back(new_addr); -- cgit v1.2.3 From 1b965831ae7588c7879d84de4e5fbd78ca614761 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 26 Feb 2010 11:01:19 +0000 Subject: made app to load usrp1e fpga images, and tested it to be working --- host/apps/CMakeLists.txt | 4 ++- host/apps/usrp1e_load_fpga.cpp | 47 +++++++++++++++++++++++++++++++++ host/lib/usrp/usrp1e/fpga-downloader.cc | 6 ++--- 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 host/apps/usrp1e_load_fpga.cpp (limited to 'host/lib/usrp') diff --git a/host/apps/CMakeLists.txt b/host/apps/CMakeLists.txt index f4428f958..a7068e5a4 100644 --- a/host/apps/CMakeLists.txt +++ b/host/apps/CMakeLists.txt @@ -16,7 +16,9 @@ # ADD_EXECUTABLE(discover_usrps discover_usrps.cpp) - TARGET_LINK_LIBRARIES(discover_usrps uhd) +ADD_EXECUTABLE(usrp1e_load_fpga usrp1e_load_fpga.cpp) +TARGET_LINK_LIBRARIES(usrp1e_load_fpga uhd) + INSTALL(TARGETS discover_usrps RUNTIME DESTINATION ${RUNTIME_DIR}) diff --git a/host/apps/usrp1e_load_fpga.cpp b/host/apps/usrp1e_load_fpga.cpp new file mode 100644 index 000000000..d5960b391 --- /dev/null +++ b/host/apps/usrp1e_load_fpga.cpp @@ -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 . +// + +#include +#include +#include +#include + +namespace po = boost::program_options; + +int main(int argc, char *argv[]){ + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("file", po::value(), "path to fpga bin file") + ; + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + //print the help message + if (vm.count("help") or vm.count("file") == 0){ + std::cout << boost::format("USRP1E Load FPGA %s") % desc << std::endl; + return ~0; + } + + //load the fpga + std::string file = vm["file"].as(); + uhd::usrp::usrp1e::load_fpga(file); + + return 0; +} diff --git a/host/lib/usrp/usrp1e/fpga-downloader.cc b/host/lib/usrp/usrp1e/fpga-downloader.cc index 15023d945..f7c78b875 100644 --- a/host/lib/usrp/usrp1e/fpga-downloader.cc +++ b/host/lib/usrp/usrp1e/fpga-downloader.cc @@ -43,7 +43,7 @@ const unsigned int PROG_B = 175; const unsigned int DONE = 173; const unsigned int INIT_B = 114; -static std::string bit_file = "safe_u1e.bin"; +//static std::string bit_file = "safe_u1e.bin"; const int BUF_SIZE = 4096; @@ -198,7 +198,7 @@ void spidev::send(char *buf, char *rbuf, unsigned int nbytes) } -static void send_file_to_fpga(std::string &file_name, gpio &error, gpio &done) +static void send_file_to_fpga(const std::string &file_name, gpio &error, gpio &done) { std::ifstream bitstream; @@ -258,5 +258,5 @@ void uhd::usrp::usrp1e::load_fpga(const std::string &bin_file){ std::cout << "Done = " << gpio_done.get_value() << std::endl; - send_file_to_fpga(bit_file, gpio_init_b, gpio_done); + send_file_to_fpga(bin_file, gpio_init_b, gpio_done); } -- cgit v1.2.3 From 606b896cb964c38ddfed0f0e5785237f9a4d0034 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 26 Feb 2010 18:57:03 -0800 Subject: fix for io types --- host/lib/usrp/usrp2/io_impl.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 43334ddc6..c9a7b5fa4 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -26,8 +26,8 @@ using namespace uhd::usrp; /*********************************************************************** * Constants **********************************************************************/ -typedef std::complex fc32_t; -typedef std::complex sc16_t; +typedef std::complex fc32_t; +typedef std::complex sc16_t; static const float float_scale_factor = pow(2.0, 15); @@ -159,7 +159,7 @@ size_t usrp2_impl::send( const uhd::metadata_t &metadata, const std::string &type ){ - if (type == "fc32"){ + if (type == "32fc"){ size_t num_samps = boost::asio::buffer_size(buff)/sizeof(fc32_t); boost::shared_array raw_mem(new sc16_t[num_samps]); boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t)); @@ -173,7 +173,7 @@ size_t usrp2_impl::send( return send_raw(raw_buff, metadata); } - if (type == "sc16"){ + if (type == "16sc"){ #ifdef HAVE_BIG_ENDIAN return send_raw(buff, metadata); #else @@ -202,7 +202,7 @@ size_t usrp2_impl::recv( uhd::metadata_t &metadata, const std::string &type ){ - if (type == "fc32"){ + if (type == "32fc"){ size_t num_samps = boost::asio::buffer_size(buff)/sizeof(fc32_t); boost::shared_array raw_mem(new sc16_t[num_samps]); boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t)); @@ -218,7 +218,7 @@ size_t usrp2_impl::recv( return num_samps; } - if (type == "sc16"){ + if (type == "16sc"){ #ifdef HAVE_BIG_ENDIAN return recv_raw(buff, metadata); #else -- cgit v1.2.3 From 6e8473e6eef84875e2c3babb35732f8c3b2a0247 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 1 Mar 2010 11:50:14 -0800 Subject: Recv noise with uhd. --- firmware/microblaze/apps/txrx.c | 3 ++ host/apps/discover_usrps.cpp | 3 -- host/include/uhd/device_addr.hpp | 6 +-- host/include/uhd/usrp/dboard_id.hpp | 6 +-- host/lib/usrp/usrp2/dsp_impl.cpp | 12 +++++- host/lib/usrp/usrp2/fw_common.h | 1 + host/lib/usrp/usrp2/io_impl.cpp | 86 +++++++++++++++++++++++++------------ host/lib/usrp/usrp2/usrp2_impl.hpp | 3 ++ 8 files changed, 82 insertions(+), 38 deletions(-) (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 1724284b0..dccb2bdc9 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -430,6 +430,8 @@ void handle_udp_ctrl_packet( ******************************************************************/ case USRP2_CTRL_ID_SETUP_THIS_DDC_FOR_ME_BRO: dsp_rx_regs->freq = ctrl_data_in->data.ddc_args.freq_word; + dsp_rx_regs->scale_iq = ctrl_data_in->data.ddc_args.scale_iq; + dsp_rx_regs->rx_mux = 0x00 | (0x01 << 2); //TODO fill in from control //setup the interp and half band filters { @@ -471,6 +473,7 @@ void handle_udp_ctrl_packet( case USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO: dsp_tx_regs->freq = ctrl_data_in->data.duc_args.freq_word; dsp_tx_regs->scale_iq = ctrl_data_in->data.duc_args.scale_iq; + dsp_tx_regs->tx_mux = 0x01; //TODO fill in from control //setup the interp and half band filters { diff --git a/host/apps/discover_usrps.cpp b/host/apps/discover_usrps.cpp index 5172a4a26..20ac1f9ed 100644 --- a/host/apps/discover_usrps.cpp +++ b/host/apps/discover_usrps.cpp @@ -63,9 +63,6 @@ int main(int argc, char *argv[]){ std::cout << "-- USRP Device " << i << std::endl; std::cout << "--------------------------------------------------" << std::endl; std::cout << device_addrs[i] << std::endl << std::endl; - //make each device just to test (TODO: remove this) - uhd::device::sptr dev = uhd::device::make(device_addrs[i]); - std::cout << wax::cast((*dev)[uhd::DEVICE_PROP_MBOARD][uhd::MBOARD_PROP_NAME]) << std::endl; } return 0; diff --git a/host/include/uhd/device_addr.hpp b/host/include/uhd/device_addr.hpp index d02febd6c..ed538453a 100644 --- a/host/include/uhd/device_addr.hpp +++ b/host/include/uhd/device_addr.hpp @@ -56,9 +56,9 @@ namespace uhd{ * \param device_addr a device address instance * \return the string representation */ - struct device_addr{ - static std::string to_string(const device_addr_t &device_addr); - }; + namespace device_addr{ + std::string to_string(const device_addr_t &device_addr); + } } //namespace uhd diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 8e904ff33..65e3d5707 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -28,9 +28,9 @@ enum dboard_id_t{ ID_BASIC_RX = 0x0001 }; -struct dboard_id{ - static std::string to_string(const dboard_id_t &id); -}; +namespace dboard_id{ + std::string to_string(const dboard_id_t &id); +} }} //namespace diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 22c00d99a..e5c4a4245 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -36,6 +36,10 @@ static uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t return freq_word; } +static uint32_t calculate_iq_scale_word(int16_t i, int16_t q){ + return ((i & 0xffff) << 16) | ((q & 0xffff) << 0); +} + void usrp2_impl::init_ddc_config(void){ //create the ddc in the rx dsp dict _rx_dsps["ddc0"] = wax_obj_proxy( @@ -61,6 +65,10 @@ void usrp2_impl::update_ddc_config(void){ calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq()) ); out_data.data.ddc_args.decim = htonl(_ddc_decim); + static const uint32_t default_rx_scale_iq = 1024; + out_data.data.ddc_args.scale_iq = htonl( + calculate_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) + ); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); @@ -209,7 +217,9 @@ void usrp2_impl::update_duc_config(void){ calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq()) ); out_data.data.duc_args.interp = htonl(_duc_interp); - out_data.data.duc_args.scale_iq = htonl(scale); + out_data.data.duc_args.scale_iq = htonl( + calculate_iq_scale_word(scale, scale) + ); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 3def8ddaa..aca0abb28 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -168,6 +168,7 @@ typedef struct{ struct { uint32_t freq_word; uint32_t decim; + uint32_t scale_iq; } ddc_args; struct { uint8_t enabled; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index c9a7b5fa4..9c7a41e49 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -22,6 +22,7 @@ using namespace uhd; using namespace uhd::usrp; +namespace asio = boost::asio; /*********************************************************************** * Constants @@ -38,28 +39,28 @@ static const size_t max_vrt_header_words = 5; * Helper Functions **********************************************************************/ static inline void host_floats_to_usrp2_shorts( - int16_t *usrp2_shorts, + short *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)); + usrp2_shorts[i] = htons(short(host_floats[i]*float_scale_factor)); } } static inline void usrp2_shorts_to_host_floats( float *host_floats, - const int16_t *usrp2_shorts, + const short *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); + host_floats[i] = float(short(ntohs(usrp2_shorts[i])))/float_scale_factor; } } static inline void host_shorts_to_usrp2_shorts( - int16_t *usrp2_shorts, - const int16_t *host_shorts, + short *usrp2_shorts, + const short *host_shorts, size_t num_samps ){ for(size_t i = 0; i < num_samps; i++){ @@ -68,8 +69,8 @@ static inline void host_shorts_to_usrp2_shorts( } static inline void usrp2_shorts_to_host_shorts( - int16_t *host_shorts, - const int16_t *usrp2_shorts, + short *host_shorts, + const short *usrp2_shorts, size_t num_samps ){ for(size_t i = 0; i < num_samps; i++){ @@ -102,16 +103,17 @@ size_t usrp2_impl::send_raw( } vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0; vrt_hdr_flags |= (metadata.end_of_burst)? (0x1 << 24) : 0; + num_vrt_hdr_words += asio::buffer_size(buff)/sizeof(uint32_t); //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) + (num_vrt_hdr_words & 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[0] = asio::buffer(&vrt_hdr, vrt_hdr_size); buffs[1] = buff; //send and return number of samples @@ -125,11 +127,33 @@ size_t usrp2_impl::recv_raw( const boost::asio::mutable_buffer &buff, uhd::metadata_t &metadata ){ + //handle the case where there is spillover + if (asio::buffer_size(_splillover_buff) != 0){ + size_t bytes_to_copy = std::min( + asio::buffer_size(_splillover_buff), + asio::buffer_size(buff) + ); + std::memcpy( + asio::buffer_cast(buff), + asio::buffer_cast(_splillover_buff), + bytes_to_copy + ); + _splillover_buff = asio::buffer( + asio::buffer_cast(_splillover_buff)+bytes_to_copy, + asio::buffer_size(_splillover_buff)-bytes_to_copy + ); + //std::cout << boost::format("Copied spillover %d samples") % (bytes_to_copy/sizeof(sc16_t)) << std::endl; + return bytes_to_copy/sizeof(sc16_t); + } + //load the buffer vector - std::vector buffs(2); + std::vector buffs(3); uint32_t vrt_hdr[max_vrt_header_words]; - buffs[0] = boost::asio::buffer(vrt_hdr, max_vrt_header_words); - buffs[1] = buff; + 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) + ); + buffs[2] = asio::buffer(_spillover_mem, _mtu); //receive into the buffers size_t bytes_recvd = _data_transport->recv(buffs); @@ -146,9 +170,15 @@ size_t usrp2_impl::recv_raw( 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); + //extract the number of bytes received + size_t num_words = (vrt_header & 0xffff) - max_vrt_header_words; + size_t num_bytes = num_words*sizeof(uint32_t); + + //handle the case where spillover memory was used + size_t spillover_size = num_bytes - std::min(num_bytes, asio::buffer_size(buff)); + _splillover_buff = asio::buffer(_spillover_mem, spillover_size); + + return (num_bytes - spillover_size)/sizeof(sc16_t); } /*********************************************************************** @@ -160,13 +190,13 @@ size_t usrp2_impl::send( const std::string &type ){ if (type == "32fc"){ - size_t num_samps = boost::asio::buffer_size(buff)/sizeof(fc32_t); + size_t num_samps = asio::buffer_size(buff)/sizeof(fc32_t); boost::shared_array 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(raw_buff), - boost::asio::buffer_cast(buff), + asio::buffer_cast(raw_buff), + asio::buffer_cast(buff), num_samps*2 //double for complex ); @@ -177,13 +207,13 @@ size_t usrp2_impl::send( #ifdef HAVE_BIG_ENDIAN return send_raw(buff, metadata); #else - size_t num_samps = boost::asio::buffer_size(buff)/sizeof(sc16_t); + size_t num_samps = asio::buffer_size(buff)/sizeof(sc16_t); boost::shared_array 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(raw_buff), - boost::asio::buffer_cast(buff), + asio::buffer_cast(raw_buff), + asio::buffer_cast(buff), num_samps*2 //double for complex ); @@ -203,15 +233,15 @@ size_t usrp2_impl::recv( const std::string &type ){ if (type == "32fc"){ - size_t num_samps = boost::asio::buffer_size(buff)/sizeof(fc32_t); + size_t num_samps = asio::buffer_size(buff)/sizeof(fc32_t); boost::shared_array 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(buff), - boost::asio::buffer_cast(raw_buff), + asio::buffer_cast(buff), + asio::buffer_cast(raw_buff), num_samps*2 //double for complex ); @@ -222,15 +252,15 @@ size_t usrp2_impl::recv( #ifdef HAVE_BIG_ENDIAN return recv_raw(buff, metadata); #else - size_t num_samps = boost::asio::buffer_size(buff)/sizeof(sc16_t); + size_t num_samps = asio::buffer_size(buff)/sizeof(sc16_t); boost::shared_array 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(buff), - boost::asio::buffer_cast(raw_buff), + asio::buffer_cast(buff), + asio::buffer_cast(raw_buff), num_samps*2 //double for complex ); diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 9a4c42d42..47b01d1b1 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -106,6 +106,9 @@ private: size_t send_raw(const boost::asio::const_buffer &, const uhd::metadata_t &); size_t recv_raw(const boost::asio::mutable_buffer &, uhd::metadata_t &); uhd::dict _stream_id_to_packet_seq; + static const size_t _mtu = 1500; + uint8_t _spillover_mem[_mtu]; + boost::asio::mutable_buffer _splillover_buff; //udp transports for control and data uhd::transport::udp::sptr _ctrl_transport; -- cgit v1.2.3 From 451067295399e357d73c9bfdeef5f2ad040e0243 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 1 Mar 2010 16:13:30 -0800 Subject: Send the number of samples per datagram over the control. Worked on the io impl for usrp2 (added loop unrolls and 32 bit buffers). Added some vrt rx constants to the fw common used by host and fw. Removed the MTU prop and added a general device prop for num samples. --- firmware/microblaze/apps/txrx.c | 45 ++++------- host/include/uhd/props.hpp | 5 +- host/include/uhd/utils.hpp | 5 ++ host/lib/usrp/usrp2/dsp_impl.cpp | 16 ++-- host/lib/usrp/usrp2/fw_common.h | 5 ++ host/lib/usrp/usrp2/io_impl.cpp | 153 +++++++++++++++++++++--------------- host/lib/usrp/usrp2/mboard_impl.cpp | 11 +-- host/lib/usrp/usrp2/usrp2_impl.cpp | 15 +++- host/lib/usrp/usrp2/usrp2_impl.hpp | 11 ++- 9 files changed, 152 insertions(+), 114 deletions(-) (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index dccb2bdc9..e4e40e7e0 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -457,6 +457,8 @@ void handle_udp_ctrl_packet( case USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO: time_secs = ctrl_data_in->data.streaming.secs; time_ticks = ctrl_data_in->data.streaming.ticks; + streaming_items_per_frame = ctrl_data_in->data.streaming.samples; + if (ctrl_data_in->data.streaming.enabled == 0){ stop_rx_cmd(); } @@ -518,8 +520,15 @@ eth_pkt_inspector(dbsm_t *sm, int bufno) //------------------------------------------------------------------ -#define VRT_HEADER_WORDS 5 -#define VRT_TRAILER_WORDS 0 +static uint16_t get_vrt_packet_words(void){ + return streaming_items_per_frame + \ + USRP2_HOST_RX_VRT_HEADER_WORDS32 + \ + USRP2_HOST_RX_VRT_TRAILER_WORDS32; +} + +static bool vrt_has_trailer(void){ + return USRP2_HOST_RX_VRT_TRAILER_WORDS32 > 0; +} void restart_streaming(void) @@ -530,10 +539,10 @@ restart_streaming(void) sr_rx_ctrl->clear_overrun = 1; // reset sr_rx_ctrl->vrt_header = (0 | VRTH_PT_IF_DATA_WITH_SID - | ((VRT_TRAILER_WORDS)? VRTH_HAS_TRAILER : 0) + | (vrt_has_trailer()? VRTH_HAS_TRAILER : 0) | VRTH_TSI_OTHER | VRTH_TSF_SAMPLE_CNT - | (VRT_HEADER_WORDS+streaming_items_per_frame+VRT_TRAILER_WORDS)); + ); sr_rx_ctrl->vrt_stream_id = 0; sr_rx_ctrl->vrt_trailer = 0; @@ -595,8 +604,9 @@ start_rx_streaming_cmd(void) } mem _AL4; memset(&mem, 0, sizeof(mem)); - streaming_items_per_frame = (1500)/sizeof(uint32_t) - (DSP_TX_FIRST_LINE + VRT_HEADER_WORDS + VRT_TRAILER_WORDS); //FIXME - mem.ctrl_word = (VRT_HEADER_WORDS+streaming_items_per_frame+VRT_TRAILER_WORDS)*sizeof(uint32_t) | 1 << 16; + printf("samples per frame: %d\n", streaming_items_per_frame); + printf("words in a vrt packet %d\n", get_vrt_packet_words()); + mem.ctrl_word = get_vrt_packet_words()*sizeof(uint32_t) | 1 << 16; memcpy_wa(buffer_ram(DSP_RX_BUF_0), &mem, sizeof(mem)); memcpy_wa(buffer_ram(DSP_RX_BUF_1), &mem, sizeof(mem)); @@ -653,25 +663,6 @@ stop_rx_cmd(void) } - -/*static void -setup_tx() -{ - sr_tx_ctrl->clear_state = 1; - bp_clear_buf(DSP_TX_BUF_0); - bp_clear_buf(DSP_TX_BUF_1); - - int tx_scale = 256; - int interp = 32; - - // setup some defaults - - dsp_tx_regs->freq = 0; - dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; - dsp_tx_regs->interp_rate = interp; -}*/ - - #if (FW_SETS_SEQNO) /* * Debugging ONLY. This will be handled by the tx_protocol_engine. @@ -760,10 +751,6 @@ main(void) // tell app_common that this dbsm could be sending to the ethernet ac_could_be_sending_to_eth = &dsp_rx_sm; - - // program tx registers - //setup_tx(); - // kick off the state machine dbsm_start(&dsp_tx_sm); diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index 2b6daf6c5..cf301d4bd 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -65,7 +65,9 @@ namespace uhd{ enum device_prop_t{ DEVICE_PROP_NAME, //ro, std::string DEVICE_PROP_MBOARD, //ro, wax::obj - DEVICE_PROP_MBOARD_NAMES //ro, prop_names_t + DEVICE_PROP_MBOARD_NAMES, //ro, prop_names_t + DEVICE_PROP_MAX_RX_SAMPLES, //ro, size_t + DEVICE_PROP_MAX_TX_SAMPLES //ro, size_t }; /*! @@ -77,7 +79,6 @@ namespace uhd{ enum mboard_prop_t{ MBOARD_PROP_NAME, //ro, std::string MBOARD_PROP_OTHERS, //ro, prop_names_t - MBOARD_PROP_MTU, //ro, size_t MBOARD_PROP_CLOCK_RATE, //ro, freq_t MBOARD_PROP_RX_DSP, //ro, wax::obj MBOARD_PROP_RX_DSP_NAMES, //ro, prop_names_t diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 4331aba7e..9bbdc83c9 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -57,6 +57,11 @@ namespace std{ return last != std::find(first, last, elem); } + template + bool has(const V &vector, const T &elem){ + return has(vector.begin(), vector.end(), elem); + } + template T sum(const T &a, const T &b){ return a + b; diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index e5c4a4245..a57f5ff2d 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -48,7 +48,7 @@ void usrp2_impl::init_ddc_config(void){ ); //initial config and update - _ddc_decim = 16; + _ddc_decim = 64; _ddc_freq = 0; update_ddc_config(); @@ -82,6 +82,12 @@ void usrp2_impl::update_ddc_enabled(void){ out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0; out_data.data.streaming.secs = htonl(_ddc_stream_at.secs); out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks); + out_data.data.streaming.samples = htonl( + _mtu/sizeof(uint32_t) - + USRP2_HOST_RX_VRT_HEADER_WORDS32 - + USRP2_HOST_RX_VRT_TRAILER_WORDS32 - + ((2 + 14 + 20 + 8)/sizeof(uint32_t)) //size of headers (pad, eth, ip, udp) + ); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); @@ -151,8 +157,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ if (key_name == "decim"){ size_t new_decim = wax::cast(val); ASSERT_THROW(std::has( - _allowed_decim_and_interp_rates.begin(), - _allowed_decim_and_interp_rates.end(), + _allowed_decim_and_interp_rates, new_decim )); _ddc_decim = new_decim; //shadow @@ -196,7 +201,7 @@ void usrp2_impl::init_duc_config(void){ ); //initial config and update - _duc_interp = 16; + _duc_interp = 64; _duc_freq = 0; update_duc_config(); } @@ -280,8 +285,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ if (key_name == "interp"){ size_t new_interp = wax::cast(val); ASSERT_THROW(std::has( - _allowed_decim_and_interp_rates.begin(), - _allowed_decim_and_interp_rates.end(), + _allowed_decim_and_interp_rates, new_interp )); _duc_interp = new_interp; //shadow diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index aca0abb28..8e4b2ba35 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -27,6 +27,10 @@ extern "C" { #endif +// size of the vrt header and trailer to the host +#define USRP2_HOST_RX_VRT_HEADER_WORDS32 5 +#define USRP2_HOST_RX_VRT_TRAILER_WORDS32 1 //FIXME fpga sets wrong header size when no trailer present + // udp ports for the usrp2 communication // Dynamic and/or private ports: 49152-65535 #define USRP2_UDP_CTRL_PORT 49152 @@ -175,6 +179,7 @@ typedef struct{ uint8_t _pad[3]; uint32_t secs; uint32_t ticks; + uint32_t samples; } streaming; struct { uint32_t freq_word; 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 -#include #include #include "usrp2_impl.hpp" @@ -27,55 +26,80 @@ namespace asio = boost::asio; /*********************************************************************** * Constants **********************************************************************/ -typedef std::complex fc32_t; -typedef std::complex sc16_t; +typedef std::complex fc32_t; +typedef std::complex 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 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 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 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(raw_buff), - asio::buffer_cast(buff), - num_samps*2 //double for complex + host_floats_to_usrp2_items( + asio::buffer_cast(raw_buff), + asio::buffer_cast(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 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(raw_buff), - asio::buffer_cast(buff), - num_samps*2 //double for complex + host_items_to_usrp2_items( + asio::buffer_cast(raw_buff), + asio::buffer_cast(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 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(buff), - asio::buffer_cast(raw_buff), - num_samps*2 //double for complex + usrp2_items_to_host_floats( + asio::buffer_cast(buff), + asio::buffer_cast(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 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(buff), - asio::buffer_cast(raw_buff), - num_samps*2 //double for complex + usrp2_items_to_host_items( + asio::buffer_cast(buff), + asio::buffer_cast(raw_buff), + num_samps ); return num_samps; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index cc73b229c..8e682a675 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -82,6 +82,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_RX_DBOARD: + ASSERT_THROW(_rx_dboards.has_key(name)); val = _rx_dboards[name].get_link(); return; @@ -90,6 +91,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_TX_DBOARD: + ASSERT_THROW(_tx_dboards.has_key(name)); val = _tx_dboards[name].get_link(); return; @@ -97,17 +99,12 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = prop_names_t(_tx_dboards.get_keys()); return; - case MBOARD_PROP_MTU: - // FIXME we dont know the real MTU... - // give them something to fragment about - val = size_t(1500); - return; - case MBOARD_PROP_CLOCK_RATE: val = freq_t(get_master_clock_freq()); return; case MBOARD_PROP_RX_DSP: + ASSERT_THROW(_rx_dsps.has_key(name)); val = _rx_dsps[name].get_link(); return; @@ -116,6 +113,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_TX_DSP: + ASSERT_THROW(_tx_dsps.has_key(name)); val = _tx_dsps[name].get_link(); return; @@ -183,7 +181,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_NAME: case MBOARD_PROP_OTHERS: - case MBOARD_PROP_MTU: case MBOARD_PROP_CLOCK_RATE: case MBOARD_PROP_RX_DSP: case MBOARD_PROP_RX_DSP_NAMES: diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 06876d241..700f94ae1 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -133,9 +133,8 @@ 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))); + //init the send and recv io + io_init(); } @@ -197,12 +196,22 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ return; case DEVICE_PROP_MBOARD: + ASSERT_THROW(_mboards.has_key(name)); val = _mboards[name].get_link(); return; case DEVICE_PROP_MBOARD_NAMES: val = prop_names_t(_mboards.get_keys()); return; + + case DEVICE_PROP_MAX_RX_SAMPLES: + val = size_t(_max_samples_per_packet); + return; + + case DEVICE_PROP_MAX_TX_SAMPLES: + val = size_t(_max_samples_per_packet); + return; + } } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 47b01d1b1..43f32c6e6 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -105,10 +105,15 @@ private: //the raw io interface (samples are in the usrp2 native format) size_t send_raw(const boost::asio::const_buffer &, const uhd::metadata_t &); size_t recv_raw(const boost::asio::mutable_buffer &, uhd::metadata_t &); - uhd::dict _stream_id_to_packet_seq; - static const size_t _mtu = 1500; - uint8_t _spillover_mem[_mtu]; + uhd::dict _tx_stream_id_to_packet_seq; + uhd::dict _rx_stream_id_to_packet_seq; + static const size_t _mtu = 1500; //FIXME we have no idea + static const size_t _max_samples_per_packet = _mtu/sizeof(uint32_t); + uint32_t _tmp_send_mem[_mtu/sizeof(uint32_t)]; + uint32_t _tmp_recv_mem[_mtu/sizeof(uint32_t)]; + uint32_t _spillover_mem[_mtu/sizeof(uint32_t)]; boost::asio::mutable_buffer _splillover_buff; + void io_init(void); //udp transports for control and data uhd::transport::udp::sptr _ctrl_transport; -- cgit v1.2.3 From 13bd67b4949a91df5e6696e708c935266b14c502 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 2 Mar 2010 14:48:11 -0800 Subject: The net common is too slow in usrp2 firmware to figure out if its vrt data. Added a custom function to tell if a packet is vrt data, seems to be feeding fast enough at this rate... Fixed some buffer size calculation logic. --- firmware/microblaze/apps/txrx.c | 28 ++++++++++++++++------------ firmware/microblaze/lib/net_common.c | 11 +++++++++++ firmware/microblaze/lib/net_common.h | 1 + host/lib/usrp/usrp2/dsp_impl.cpp | 7 +------ host/lib/usrp/usrp2/io_impl.cpp | 11 ++++++----- host/lib/usrp/usrp2/usrp2_impl.hpp | 7 ++++++- 6 files changed, 41 insertions(+), 24 deletions(-) (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index e4e40e7e0..9c3caa4f2 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -158,19 +158,10 @@ static struct ip_addr get_my_ip_addr(void){ return addr; } -static bool _is_data; - void handle_udp_data_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ - //forward this data to the dsp when the payload is sufficient - //the small payload is used to give the device the udp source port - if (payload_len > sizeof(uint32_t)){ - _is_data = true; - return; - } - //its a tiny payload, load the fast-path variables fp_mac_addr_src = get_my_eth_mac_addr(); arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst); @@ -513,9 +504,18 @@ void handle_udp_ctrl_packet( static bool eth_pkt_inspector(dbsm_t *sm, int bufno) { - _is_data = false; - handle_eth_packet(buffer_ram(bufno), buffer_pool_status->last_line[bufno] - 3); - return !_is_data; + //extract buffer point and length + uint32_t *buff = (uint32_t *)buffer_ram(bufno); + size_t len = buffer_pool_status->last_line[bufno] - 3; + + //treat this as fast-path data? + if (is_udp_packet_with_vrt(buff, len, USRP2_UDP_DATA_PORT)){ + return false; + } + + //pass it to the slow-path handler + handle_eth_packet(buff, len); + return true; } //------------------------------------------------------------------ @@ -751,6 +751,10 @@ main(void) // tell app_common that this dbsm could be sending to the ethernet ac_could_be_sending_to_eth = &dsp_rx_sm; + sr_tx_ctrl->clear_state = 1; + bp_clear_buf(DSP_TX_BUF_0); + bp_clear_buf(DSP_TX_BUF_1); + // kick off the state machine dbsm_start(&dsp_tx_sm); diff --git a/firmware/microblaze/lib/net_common.c b/firmware/microblaze/lib/net_common.c index 693502d18..ab7aadca9 100644 --- a/firmware/microblaze/lib/net_common.c +++ b/firmware/microblaze/lib/net_common.c @@ -378,6 +378,17 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size) } } +bool is_udp_packet_with_vrt(uint32_t *p, size_t nlines, int port){ + struct ip_hdr *ip = (struct ip_hdr *)(p + 4); + struct udp_hdr *udp = (struct udp_hdr *)(((char *)ip) + IP_HLEN); + uint32_t *payload = (uint32_t *)(((char *)udp) + UDP_HLEN); + return \ + (p[3] & 0xffff) == ETHERTYPE_IPV4 && + IPH_PROTO(ip) == IP_PROTO_UDP && + udp->dest == port && + payload[0] != 0; //must be non zero vrt header +} + void handle_eth_packet(uint32_t *p, size_t nlines) { diff --git a/firmware/microblaze/lib/net_common.h b/firmware/microblaze/lib/net_common.h index cfba43412..1a7052f71 100644 --- a/firmware/microblaze/lib/net_common.h +++ b/firmware/microblaze/lib/net_common.h @@ -56,5 +56,6 @@ void send_udp_pkt(int src_port, struct socket_address dst, void handle_eth_packet(uint32_t *p, size_t nlines); +bool is_udp_packet_with_vrt(uint32_t *p, size_t nlines, int port); #endif /* INCLUDED_NET_COMMON_H */ diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index a57f5ff2d..8fdfd685f 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -82,12 +82,7 @@ void usrp2_impl::update_ddc_enabled(void){ out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0; out_data.data.streaming.secs = htonl(_ddc_stream_at.secs); out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks); - out_data.data.streaming.samples = htonl( - _mtu/sizeof(uint32_t) - - USRP2_HOST_RX_VRT_HEADER_WORDS32 - - USRP2_HOST_RX_VRT_TRAILER_WORDS32 - - ((2 + 14 + 20 + 8)/sizeof(uint32_t)) //size of headers (pad, eth, ip, udp) - ); + out_data.data.streaming.samples = htonl(_max_samples_per_packet); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 8b45a708a..0ca2409c3 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -127,12 +127,11 @@ size_t usrp2_impl::send_raw( } vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0; vrt_hdr_flags |= (metadata.end_of_burst)? (0x1 << 24) : 0; - num_vrt_hdr_words += asio::buffer_size(buff)/sizeof(uint32_t); //fill in complete header word vrt_hdr[0] = htonl(vrt_hdr_flags | ((_tx_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) | - (num_vrt_hdr_words & 0xffff) + ((num_vrt_hdr_words + asio::buffer_size(buff)/sizeof(uint32_t)) & 0xffff) ); //load the buffer vector @@ -151,6 +150,8 @@ size_t usrp2_impl::recv_raw( const boost::asio::mutable_buffer &buff, uhd::metadata_t &metadata ){ + metadata = metadata_t(); //clear metadata + //handle the case where there is spillover if (asio::buffer_size(_splillover_buff) != 0){ size_t bytes_to_copy = std::min( @@ -198,9 +199,9 @@ size_t usrp2_impl::recv_raw( _rx_stream_id_to_packet_seq[metadata.stream_id] = my_seq; //extract the number of bytes received - 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_words = (vrt_header & 0xffff) - + USRP2_HOST_RX_VRT_HEADER_WORDS32 - + USRP2_HOST_RX_VRT_TRAILER_WORDS32; size_t num_bytes = num_words*sizeof(uint32_t); //handle the case where spillover memory was used diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 43f32c6e6..037aed477 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -108,7 +108,12 @@ private: uhd::dict _tx_stream_id_to_packet_seq; uhd::dict _rx_stream_id_to_packet_seq; static const size_t _mtu = 1500; //FIXME we have no idea - static const size_t _max_samples_per_packet = _mtu/sizeof(uint32_t); + static const size_t _max_samples_per_packet = + _mtu/sizeof(uint32_t) - + USRP2_HOST_RX_VRT_HEADER_WORDS32 - + USRP2_HOST_RX_VRT_TRAILER_WORDS32 - + ((2 + 14 + 20 + 8)/sizeof(uint32_t)) //size of headers (pad, eth, ip, udp) + ; uint32_t _tmp_send_mem[_mtu/sizeof(uint32_t)]; uint32_t _tmp_recv_mem[_mtu/sizeof(uint32_t)]; uint32_t _spillover_mem[_mtu/sizeof(uint32_t)]; -- cgit v1.2.3 From 4efafcc2e20b9a980800a979edf5ea7a493b6462 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 2 Mar 2010 22:07:17 -0800 Subject: Expanded the UDP api: We can make simple udp transports for discovery and control. We can support a udp zero copy transport (currently just asio). Reworked the io_impl for usrp2 to work with the zero copy api. So far, all of this untested other than compiling. A cut-down vrt library is in the works to simplify the io impl. --- host/include/uhd/transport/CMakeLists.txt | 4 +- host/include/uhd/transport/smart_buffer.hpp | 45 ++++++ host/include/uhd/transport/udp.hpp | 76 ---------- host/include/uhd/transport/udp_simple.hpp | 79 +++++++++++ host/include/uhd/transport/udp_zero_copy.hpp | 76 ++++++++++ host/include/uhd/usrp/usrp2.hpp | 10 ++ host/lib/CMakeLists.txt | 9 +- host/lib/transport/udp.cpp | 98 ------------- host/lib/transport/udp_simple.cpp | 133 ++++++++++++++++++ host/lib/transport/udp_zero_copy_none.cpp | 117 ++++++++++++++++ host/lib/usrp/usrp2/io_impl.cpp | 202 +++++++++++---------------- host/lib/usrp/usrp2/usrp2_impl.cpp | 18 ++- host/lib/usrp/usrp2/usrp2_impl.hpp | 24 ++-- 13 files changed, 577 insertions(+), 314 deletions(-) create mode 100644 host/include/uhd/transport/smart_buffer.hpp delete mode 100644 host/include/uhd/transport/udp.hpp create mode 100644 host/include/uhd/transport/udp_simple.hpp create mode 100644 host/include/uhd/transport/udp_zero_copy.hpp delete mode 100644 host/lib/transport/udp.cpp create mode 100644 host/lib/transport/udp_simple.cpp create mode 100644 host/lib/transport/udp_zero_copy_none.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index b786eb945..ba8b33cc5 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -17,6 +17,8 @@ INSTALL(FILES - udp.hpp + smart_buffer.hpp + udp_simple.hpp + udp_zero_copy.hpp DESTINATION ${HEADER_DIR}/uhd/transport ) diff --git a/host/include/uhd/transport/smart_buffer.hpp b/host/include/uhd/transport/smart_buffer.hpp new file mode 100644 index 000000000..914c02f50 --- /dev/null +++ b/host/include/uhd/transport/smart_buffer.hpp @@ -0,0 +1,45 @@ +// +// 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 . +// + +#include +#include +#include + +#ifndef INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP +#define INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP + +namespace uhd{ namespace transport{ + +/*! + * A buffer that knows how to free itself: + * + * This is just the smart buffer interface. + * A transport implementation will have its own + * internal (custom) smart buffer implementation. + * + * A smart buffer contains a boost asio const buffer. + * On destruction, the buffer contents will be freed. + */ +class smart_buffer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + virtual const boost::asio::const_buffer &get(void) const = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP */ diff --git a/host/include/uhd/transport/udp.hpp b/host/include/uhd/transport/udp.hpp deleted file mode 100644 index 8c6fb096f..000000000 --- a/host/include/uhd/transport/udp.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// 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 . -// - -#include -#include -#include - -#ifndef INCLUDED_UHD_TRANSPORT_UDP_HPP -#define INCLUDED_UHD_TRANSPORT_UDP_HPP - -namespace uhd{ namespace transport{ - -class udp : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - /*! - * Make a new udp transport. - * The address will be resolved, it can be a host name or ipv4. - * The port will be resolved, it can be a port type or number. - * \param addr a string representing the destination address - * \param port a string representing the destination port - * \param bcast if true, enable the broadcast option on the socket - */ - static sptr make(const std::string &addr, const std::string &port, bool bcast = false); - - /*! - * 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 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 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 buffs a vector of asio buffers - * \return the number of bytes received. - */ - virtual size_t recv(const std::vector &buffs) = 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; -}; - -}} //namespace - -#endif /* INCLUDED_UHD_TRANSPORT_UDP_HPP */ diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp new file mode 100644 index 000000000..8663128ec --- /dev/null +++ b/host/include/uhd/transport/udp_simple.hpp @@ -0,0 +1,79 @@ +// +// 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 . +// + +#include +#include +#include + +#ifndef INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP +#define INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP + +namespace uhd{ namespace transport{ + +class udp_simple : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new connected udp transport: + * This transport is for sending and receiving + * between this host and a single endpoint. + * The primary usage for this transport will be control transactions. + * The underlying implementation is simple and portable (not fast). + * + * The address will be resolved, it can be a host name or ipv4. + * The port will be resolved, it can be a port type or number. + * + * \param addr a string representing the destination address + * \param port a string representing the destination port + */ + static sptr make_connected(const std::string &addr, const std::string &port); + + /*! + * Make a new broadcasting udp transport: + * This transport can send udp broadcast datagrams + * and receive datagrams from multiple sources. + * The primary usage for this transport will be to discover devices. + * + * The address will be resolved, it can be a host name or ipv4. + * The port will be resolved, it can be a port type or number. + * + * \param addr a string representing the destination address + * \param port a string representing the destination port + */ + static sptr make_broadcast(const std::string &addr, const std::string &port); + + /*! + * Send a single buffer. + * Blocks until the data is sent. + * \param buff single asio buffer + * \return the number of bytes sent + */ + virtual size_t send(const boost::asio::const_buffer &buff) = 0; + + /*! + * Receive into the provided buffer. + * 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; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP */ diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp new file mode 100644 index 000000000..9c3505dd6 --- /dev/null +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -0,0 +1,76 @@ +// +// 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 . +// + +#include +#include +#include +#include + +#ifndef INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP + +namespace uhd{ namespace transport{ + +/*! + * A zero copy udp transport provides an efficient way to handle data. + * by avoiding the extra copy when recv() is called on the socket. + * Rather, the zero copy transport gives the caller a memory reference. + * The caller informs the transport when it is finished with the reference. + * + * On linux systems, the zero copy transport can use a kernel packet ring. + * If no platform specific solution is available, make returns a boost asio + * implementation that wraps the functionality around a standard recv() call. + */ +class udp_zero_copy : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new zero copy udp transport: + * This transport is for sending and receiving + * between this host and a single endpoint. + * The primary usage for this transport will be data transactions. + * The underlying implementation is fast and platform specific. + * + * The address will be resolved, it can be a host name or ipv4. + * The port will be resolved, it can be a port type or number. + * + * \param addr a string representing the destination address + * \param port a string representing the destination port + */ + static sptr make(const std::string &addr, const std::string &port); + + /*! + * Send a single buffer. + * Blocks until the data is sent. + * \param buff single asio buffer + * \return the number of bytes sent + */ + virtual size_t send(const boost::asio::const_buffer &buff) = 0; + + /*! + * Receive a buffer. + * The memory is managed by the implementation. + * Returns an empty buffer when data is not available. + * \return a smart buffer with memory and size + */ + virtual smart_buffer::sptr recv(void) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP */ diff --git a/host/include/uhd/usrp/usrp2.hpp b/host/include/uhd/usrp/usrp2.hpp index da7ec595a..b13786546 100644 --- a/host/include/uhd/usrp/usrp2.hpp +++ b/host/include/uhd/usrp/usrp2.hpp @@ -29,6 +29,11 @@ class usrp2 : public device{ public: /*! * Discover usrp2 devices over the ethernet. + * + * Recommended key/value pairs for the device hint address: + * hint["addr"] = address, where address is a resolvable address + * or ip address, which may or may not be a broadcast address. + * * This static method will be called by the device::discover. * \param hint a device addr with the usrp2 address filled in * \return a vector of device addresses for all usrp2s found @@ -37,6 +42,11 @@ public: /*! * Make a usrp2 from a device address. + * + * Required key/value pairs for the device address: + * hint["addr"] = address, where address is a resolvable address + * or ip address, which must be the specific address of a usrp2. + * * \param addr the device address * \return a device sptr to a new usrp2 */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 97f1ac52e..a52cd74a9 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -23,7 +23,7 @@ SET(libuhd_sources device_addr.cpp gain_handler.cpp wax.cpp - transport/udp.cpp + transport/udp_simple.cpp usrp/dboard/basic.cpp usrp/dboard_base.cpp usrp/dboard_id.cpp @@ -37,6 +37,13 @@ SET(libuhd_sources usrp/usrp2/usrp2_impl.cpp ) +######################################################################## +# Conditionally add the udp sources +######################################################################## +LIST(APPEND libuhd_sources + transport/udp_zero_copy_none.cpp +) + ######################################################################## # Conditionally add the usrp1e sources ######################################################################## diff --git a/host/lib/transport/udp.cpp b/host/lib/transport/udp.cpp deleted file mode 100644 index 878f71410..000000000 --- a/host/lib/transport/udp.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// -// 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 . -// - -#include -#include -#include - -/*********************************************************************** - * UDP implementation class - **********************************************************************/ -class udp_impl : public uhd::transport::udp{ -public: - //structors - udp_impl(const std::string &addr, const std::string &port, bool bcast); - ~udp_impl(void); - - //send/recv - size_t send(const std::vector &buffs); - size_t send(const boost::asio::const_buffer &buff); - size_t recv(const std::vector &buffs); - size_t recv(const boost::asio::mutable_buffer &buff); - -private: - boost::asio::ip::udp::socket *_socket; - boost::asio::ip::udp::endpoint _receiver_endpoint; - boost::asio::ip::udp::endpoint _sender_endpoint; - boost::asio::io_service _io_service; -}; - -/*********************************************************************** - * UDP public make function - **********************************************************************/ -uhd::transport::udp::sptr uhd::transport::udp::make( - const std::string &addr, - const std::string &port, - bool bcast -){ - return uhd::transport::udp::sptr(new udp_impl(addr, port, bcast)); -} - -/*********************************************************************** - * UDP implementation methods - **********************************************************************/ -udp_impl::udp_impl(const std::string &addr, const std::string &port, bool bcast){ - //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; - - // resolve the address - boost::asio::ip::udp::resolver resolver(_io_service); - boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); - _receiver_endpoint = *resolver.resolve(query); - - // Create and open the socket - _socket = new boost::asio::ip::udp::socket(_io_service); - _socket->open(boost::asio::ip::udp::v4()); - - if (bcast){ - // Allow broadcasting - boost::asio::socket_base::broadcast option(true); - _socket->set_option(option); - } - -} - -udp_impl::~udp_impl(void){ - delete _socket; -} - -size_t udp_impl::send(const std::vector &buffs){ - return _socket->send_to(buffs, _receiver_endpoint); -} - -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 std::vector &buffs){ - if (_socket->available() == 0) return 0; - return _socket->receive_from(buffs, _sender_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); -} diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp new file mode 100644 index 000000000..491cf59db --- /dev/null +++ b/host/lib/transport/udp_simple.cpp @@ -0,0 +1,133 @@ +// +// 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 . +// + +#include +#include +#include + +using namespace uhd::transport; + +/*********************************************************************** + * UDP connected implementation class + **********************************************************************/ +class udp_connected_impl : public udp_simple{ +public: + //structors + udp_connected_impl(const std::string &addr, const std::string &port); + ~udp_connected_impl(void); + + //send/recv + size_t send(const boost::asio::const_buffer &buff); + size_t recv(const boost::asio::mutable_buffer &buff); + +private: + boost::asio::ip::udp::socket *_socket; + boost::asio::io_service _io_service; +}; + +udp_connected_impl::udp_connected_impl(const std::string &addr, const std::string &port){ + //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; + + // resolve the address + boost::asio::ip::udp::resolver resolver(_io_service); + boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); + boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); + + // Create, open, and connect the socket + _socket = new boost::asio::ip::udp::socket(_io_service); + _socket->open(boost::asio::ip::udp::v4()); + _socket->connect(receiver_endpoint); +} + +udp_connected_impl::~udp_connected_impl(void){ + delete _socket; +} + +size_t udp_connected_impl::send(const boost::asio::const_buffer &buff){ + return _socket->send(boost::asio::buffer(buff)); +} + +size_t udp_connected_impl::recv(const boost::asio::mutable_buffer &buff){ + if (_socket->available() == 0) return 0; + return _socket->receive(boost::asio::buffer(buff)); +} + +/*********************************************************************** + * UDP broadcast implementation class + **********************************************************************/ +class udp_broadcast_impl : public udp_simple{ +public: + //structors + udp_broadcast_impl(const std::string &addr, const std::string &port); + ~udp_broadcast_impl(void); + + //send/recv + size_t send(const boost::asio::const_buffer &buff); + size_t recv(const boost::asio::mutable_buffer &buff); + +private: + boost::asio::ip::udp::socket *_socket; + boost::asio::ip::udp::endpoint _receiver_endpoint; + boost::asio::io_service _io_service; +}; + +udp_broadcast_impl::udp_broadcast_impl(const std::string &addr, const std::string &port){ + //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; + + // resolve the address + boost::asio::ip::udp::resolver resolver(_io_service); + boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); + _receiver_endpoint = *resolver.resolve(query); + + // Create and open the socket + _socket = new boost::asio::ip::udp::socket(_io_service); + _socket->open(boost::asio::ip::udp::v4()); + + // Allow broadcasting + boost::asio::socket_base::broadcast option(true); + _socket->set_option(option); + +} + +udp_broadcast_impl::~udp_broadcast_impl(void){ + delete _socket; +} + +size_t udp_broadcast_impl::send(const boost::asio::const_buffer &buff){ + return _socket->send_to(boost::asio::buffer(buff), _receiver_endpoint); +} + +size_t udp_broadcast_impl::recv(const boost::asio::mutable_buffer &buff){ + if (_socket->available() == 0) return 0; + boost::asio::ip::udp::endpoint sender_endpoint; + return _socket->receive_from(boost::asio::buffer(buff), sender_endpoint); +} + +/*********************************************************************** + * UDP public make functions + **********************************************************************/ +udp_simple::sptr udp_simple::make_connected( + const std::string &addr, const std::string &port +){ + return sptr(new udp_connected_impl(addr, port)); +} + +udp_simple::sptr udp_simple::make_broadcast( + const std::string &addr, const std::string &port +){ + return sptr(new udp_broadcast_impl(addr, port)); +} diff --git a/host/lib/transport/udp_zero_copy_none.cpp b/host/lib/transport/udp_zero_copy_none.cpp new file mode 100644 index 000000000..e95706d94 --- /dev/null +++ b/host/lib/transport/udp_zero_copy_none.cpp @@ -0,0 +1,117 @@ +// +// 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 . +// + +#include + +using namespace uhd::transport; + +/*********************************************************************** + * Smart buffer implementation for udp zerocopy none + * + * This smart buffer implemention houses a const buffer. + * When the smart buffer is deleted, the buffer is freed. + * The memory in the const buffer is allocated with new [], + * and so the destructor frees the buffer with delete []. + **********************************************************************/ +class smart_buffer_impl : public smart_buffer{ +public: + smart_buffer_impl(const boost::asio::const_buffer &buff){ + _buff = buff; + } + + ~smart_buffer_impl(void){ + delete [] boost::asio::buffer_cast(_buff); + } + + const boost::asio::const_buffer &get(void) const{ + return _buff; + } + +private: + boost::asio::const_buffer _buff; +}; + +/*********************************************************************** + * UDP zero copy implementation class + * + * This is the portable zero copy implementation for systems + * where a faster, platform specific solution is not available. + * + * It uses boost asio udp sockets and the standard recv() class, + * and in-fact, is not actually doing a zero-copy implementation. + **********************************************************************/ +class udp_zero_copy_impl : public udp_zero_copy{ +public: + //structors + udp_zero_copy_impl(const std::string &addr, const std::string &port); + ~udp_zero_copy_impl(void); + + //send/recv + size_t send(const boost::asio::const_buffer &buff); + smart_buffer::sptr recv(void); + +private: + boost::asio::ip::udp::socket *_socket; + boost::asio::io_service _io_service; +}; + +udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ + //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; + + // resolve the address + boost::asio::ip::udp::resolver resolver(_io_service); + boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); + boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); + + // Create, open, and connect the socket + _socket = new boost::asio::ip::udp::socket(_io_service); + _socket->open(boost::asio::ip::udp::v4()); + _socket->connect(receiver_endpoint); +} + +udp_zero_copy_impl::~udp_zero_copy_impl(void){ + delete _socket; +} + +size_t udp_zero_copy_impl::send(const boost::asio::const_buffer &buff){ + return _socket->send(boost::asio::buffer(buff)); +} + +smart_buffer::sptr udp_zero_copy_impl::recv(void){ + size_t available = _socket->available(); + + //allocate memory and create buffer + uint32_t *buff_mem = new uint32_t[available/sizeof(uint32_t)]; + boost::asio::mutable_buffer buff(buff_mem, available); + + //receive only if data is available + if (available > 0){ + _socket->receive(boost::asio::buffer(buff)); + } + + //create a new smart buffer to house the data + return smart_buffer::sptr(new smart_buffer_impl(buff)); +} + +/*********************************************************************** + * UDP zero copy make function + **********************************************************************/ +udp_zero_copy::sptr udp_zero_copy::make( + const std::string &addr, const std::string &port +){ + return sptr(new udp_zero_copy_impl(addr, port)); +} diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 0ca2409c3..6969e0a89 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -36,12 +36,12 @@ static const float floats_per_short = 1.0/shorts_per_float; * Helper Functions **********************************************************************/ void usrp2_impl::io_init(void){ - //initially empty spillover buffer - _splillover_buff = asio::buffer(_spillover_mem, 0); + //initially empty copy buffer + _rx_copy_buff = asio::buffer("", 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))); + _data_transport->send(asio::buffer(&zero_data, sizeof(zero_data))); } #define unrolled_loop(__i, __len, __inst) {\ @@ -57,6 +57,13 @@ void usrp2_impl::io_init(void){ } \ } +// set a boolean flag that indicates the endianess +#ifdef HAVE_BIG_ENDIAN +static const bool is_big_endian = true; +#else +static const bool is_big_endian = false; +#endif + static inline void host_floats_to_usrp2_items( uint32_t *usrp2_items, const fc32_t *host_floats, @@ -87,9 +94,12 @@ static inline void host_items_to_usrp2_items( const uint32_t *host_items, size_t num_samps ){ - unrolled_loop(i, num_samps, - usrp2_items[i] = htonl(host_items[i]) - ); + if (is_big_endian){ + std::memcpy(usrp2_items, host_items, num_samps*sizeof(uint32_t)); + } + else{ + unrolled_loop(i, num_samps, usrp2_items[i] = htonl(host_items[i])); + } } static inline void usrp2_items_to_host_items( @@ -97,20 +107,22 @@ static inline void usrp2_items_to_host_items( const uint32_t *usrp2_items, size_t num_samps ){ - unrolled_loop(i, num_samps, - host_items[i] = ntohl(usrp2_items[i]) - ); + if (is_big_endian){ + std::memcpy(host_items, usrp2_items, num_samps*sizeof(uint32_t)); + } + else{ + unrolled_loop(i, num_samps, host_items[i] = ntohl(usrp2_items[i])); + } } /*********************************************************************** * Send Raw Data **********************************************************************/ -size_t usrp2_impl::send_raw( - const boost::asio::const_buffer &buff, - const uhd::metadata_t &metadata -){ - std::vector buffs(2); - uint32_t vrt_hdr[7]; //max size +size_t usrp2_impl::send_raw(const uhd::metadata_t &metadata){ + size_t num_items = asio::buffer_size(_tx_copy_buff)/sizeof(uint32_t); + const uint32_t *items = asio::buffer_cast(_tx_copy_buff); + + uint32_t vrt_hdr[_tx_vrt_max_offset_words32]; uint32_t vrt_hdr_flags = 0; size_t num_vrt_hdr_words = 1; @@ -131,60 +143,30 @@ size_t usrp2_impl::send_raw( //fill in complete header word vrt_hdr[0] = htonl(vrt_hdr_flags | ((_tx_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) | - ((num_vrt_hdr_words + asio::buffer_size(buff)/sizeof(uint32_t)) & 0xffff) + ((num_vrt_hdr_words + num_items) & 0xffff) ); - //load the buffer vector - size_t vrt_hdr_size = num_vrt_hdr_words*sizeof(uint32_t); - buffs[0] = asio::buffer(&vrt_hdr, vrt_hdr_size); - buffs[1] = buff; + //copy in the vrt header (yes we left space) + std::memcpy(((uint32_t *)items) - num_vrt_hdr_words, vrt_hdr, num_vrt_hdr_words); + asio::const_buffer buff(items - num_vrt_hdr_words, (num_vrt_hdr_words + num_items)*sizeof(uint32_t)); //send and return number of samples - return (_data_transport->send(buffs) - vrt_hdr_size)/sizeof(sc16_t); + return (_data_transport->send(buff) - num_vrt_hdr_words*sizeof(uint32_t))/sizeof(sc16_t); } /*********************************************************************** * Receive Raw Data **********************************************************************/ -size_t usrp2_impl::recv_raw( - const boost::asio::mutable_buffer &buff, - uhd::metadata_t &metadata -){ - metadata = metadata_t(); //clear metadata - - //handle the case where there is spillover - if (asio::buffer_size(_splillover_buff) != 0){ - size_t bytes_to_copy = std::min( - asio::buffer_size(_splillover_buff), - asio::buffer_size(buff) - ); - std::memcpy( - asio::buffer_cast(buff), - asio::buffer_cast(_splillover_buff), - bytes_to_copy - ); - _splillover_buff = asio::buffer( - asio::buffer_cast(_splillover_buff)+bytes_to_copy, - asio::buffer_size(_splillover_buff)-bytes_to_copy - ); - //std::cout << boost::format("Copied spillover %d samples") % (bytes_to_copy/sizeof(sc16_t)) << std::endl; - return bytes_to_copy/sizeof(sc16_t); - } - - //load the buffer vector - std::vector buffs(3); - 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); +void usrp2_impl::recv_raw(uhd::metadata_t &metadata){ + //do a receive + _rx_smart_buff = _data_transport->recv(); - //receive into the buffers - size_t bytes_recvd = _data_transport->recv(buffs); - - //failure case - if (bytes_recvd < sizeof(vrt_hdr)) return 0; + //////////////////////////////////////////////////////////////////// + // !!!! FIXME this is very flawed, use a proper vrt unpacker !!!!!!! + //////////////////////////////////////////////////////////////////// //unpack the vrt header + const uint32_t *vrt_hdr = asio::buffer_cast(_rx_smart_buff->get()); metadata = uhd::metadata_t(); uint32_t vrt_header = ntohl(vrt_hdr[0]); metadata.has_stream_id = true; @@ -202,13 +184,12 @@ size_t usrp2_impl::recv_raw( size_t num_words = (vrt_header & 0xffff) - USRP2_HOST_RX_VRT_HEADER_WORDS32 - USRP2_HOST_RX_VRT_TRAILER_WORDS32; - size_t num_bytes = num_words*sizeof(uint32_t); - - //handle the case where spillover memory was used - size_t spillover_size = num_bytes - std::min(num_bytes, asio::buffer_size(buff)); - _splillover_buff = asio::buffer(_spillover_mem, spillover_size); - return (num_bytes - spillover_size)/sizeof(sc16_t); + //setup the rx buffer to point to the data + _rx_copy_buff = boost::asio::buffer( + vrt_hdr + USRP2_HOST_RX_VRT_HEADER_WORDS32, + num_words*sizeof(uint32_t) + ); } /*********************************************************************** @@ -219,37 +200,26 @@ size_t usrp2_impl::send( const uhd::metadata_t &metadata, const std::string &type ){ - if (type == "32fc"){ - size_t num_samps = asio::buffer_size(buff)/sizeof(fc32_t); - boost::asio::mutable_buffer raw_buff(_tmp_send_mem, num_samps*sizeof(sc16_t)); + uint32_t *items = _tx_mem + _tx_vrt_max_offset_words32; //offset for data + size_t num_samps = _max_samples_per_packet; - host_floats_to_usrp2_items( - asio::buffer_cast(raw_buff), - asio::buffer_cast(buff), - num_samps - ); - - return send_raw(raw_buff, metadata); + //calculate the number of samples to be copied + //and copy the samples into the send buffer + if (type == "32fc"){ + num_samps = std::min(asio::buffer_size(buff)/sizeof(fc32_t), num_samps); + host_floats_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); } - - if (type == "16sc"){ - #ifdef HAVE_BIG_ENDIAN - return send_raw(buff, metadata); - #else - size_t num_samps = asio::buffer_size(buff)/sizeof(sc16_t); - boost::asio::mutable_buffer raw_buff(_tmp_send_mem, num_samps*sizeof(sc16_t)); - - host_items_to_usrp2_items( - asio::buffer_cast(raw_buff), - asio::buffer_cast(buff), - num_samps - ); - - return send_raw(raw_buff, metadata); - #endif + else if (type == "16sc"){ + num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps); + host_items_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); + } + else{ + throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type)); } - throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type)); + //send the samples (this line seems silly, will be better with vrt lib) + _tx_copy_buff = asio::buffer(items, num_samps*sizeof(uint32_t)); + return send_raw(metadata); //return num_samps; } /*********************************************************************** @@ -260,39 +230,31 @@ size_t usrp2_impl::recv( uhd::metadata_t &metadata, const std::string &type ){ - if (type == "32fc"){ - size_t num_samps = asio::buffer_size(buff)/sizeof(fc32_t); - boost::asio::mutable_buffer raw_buff(_tmp_recv_mem, num_samps*sizeof(sc16_t)); - - num_samps = recv_raw(raw_buff, metadata); + //perform a receive if no rx data is waiting to be copied + if (asio::buffer_size(_rx_copy_buff) == 0) recv_raw(metadata); + //TODO otherwise flag the metadata to show that is is a fragment - usrp2_items_to_host_floats( - asio::buffer_cast(buff), - asio::buffer_cast(raw_buff), - num_samps - ); + //extract the number of samples available to copy + //and a pointer into the usrp2 received items memory + size_t num_samps = asio::buffer_size(_rx_copy_buff)/sizeof(uint32_t); + const uint32_t *items = asio::buffer_cast(_rx_copy_buff); - return num_samps; + //calculate the number of samples to be copied + //and copy the samples from the recv buffer + if (type == "32fc"){ + num_samps = std::min(asio::buffer_size(buff)/sizeof(fc32_t), num_samps); + usrp2_items_to_host_floats(asio::buffer_cast(buff), items, num_samps); } - - if (type == "16sc"){ - #ifdef HAVE_BIG_ENDIAN - return recv_raw(buff, metadata); - #else - size_t num_samps = asio::buffer_size(buff)/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_items_to_host_items( - asio::buffer_cast(buff), - asio::buffer_cast(raw_buff), - num_samps - ); - - return num_samps; - #endif + else if (type == "16sc"){ + num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps); + usrp2_items_to_host_items(asio::buffer_cast(buff), items, num_samps); + } + else{ + throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%s\"") % type)); } - throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%s\"") % type)); + //update the rx copy buffer to reflect the bytes copied + _rx_copy_buff = asio::buffer(items + num_samps, num_samps*sizeof(uint32_t)); + + return num_samps; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 700f94ae1..51082df15 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -23,6 +23,7 @@ using namespace uhd; using namespace uhd::usrp; +using namespace uhd::transport; /*********************************************************************** * Discovery over the udp transport @@ -33,8 +34,9 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ //create a udp transport to communicate //TODO if an addr is not provided, search all interfaces? std::string ctrl_port = boost::lexical_cast(USRP2_UDP_CTRL_PORT); - transport::udp::sptr udp_transport = \ - transport::udp::make(hint["addr"], ctrl_port, true); + udp_simple::sptr udp_transport = udp_simple::make_broadcast( + hint["addr"], ctrl_port + ); //send a hello control packet usrp2_ctrl_data_t ctrl_data_out; @@ -76,16 +78,18 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ /*********************************************************************** * Make **********************************************************************/ -#define num2str(num) (boost::lexical_cast(num)) +template std::string num2str(T num){ + return boost::lexical_cast(num); +} device::sptr usrp2::make(const device_addr_t &device_addr){ //create a control transport - transport::udp::sptr ctrl_transport = transport::udp::make( + udp_simple::sptr ctrl_transport = udp_simple::make_connected( device_addr["addr"], num2str(USRP2_UDP_CTRL_PORT) ); //create a data transport - transport::udp::sptr data_transport = transport::udp::make( + udp_zero_copy::sptr data_transport = udp_zero_copy::make( device_addr["addr"], num2str(USRP2_UDP_DATA_PORT) ); @@ -99,8 +103,8 @@ device::sptr usrp2::make(const device_addr_t &device_addr){ * Structors **********************************************************************/ usrp2_impl::usrp2_impl( - transport::udp::sptr ctrl_transport, - transport::udp::sptr data_transport + udp_simple::sptr ctrl_transport, + udp_zero_copy::sptr data_transport ){ _ctrl_transport = ctrl_transport; _data_transport = data_transport; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 037aed477..a58bf8471 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -22,7 +22,8 @@ #include #include #include -#include +#include +#include #include #include "fw_common.h" @@ -81,8 +82,8 @@ public: * \param data_transport the udp transport for data */ usrp2_impl( - uhd::transport::udp::sptr ctrl_transport, - uhd::transport::udp::sptr data_transport + uhd::transport::udp_simple::sptr ctrl_transport, + uhd::transport::udp_zero_copy::sptr data_transport ); ~usrp2_impl(void); @@ -103,8 +104,8 @@ public: private: //the raw io interface (samples are in the usrp2 native format) - size_t send_raw(const boost::asio::const_buffer &, const uhd::metadata_t &); - size_t recv_raw(const boost::asio::mutable_buffer &, uhd::metadata_t &); + size_t send_raw(const uhd::metadata_t &); + void recv_raw(uhd::metadata_t &); uhd::dict _tx_stream_id_to_packet_seq; uhd::dict _rx_stream_id_to_packet_seq; static const size_t _mtu = 1500; //FIXME we have no idea @@ -114,15 +115,16 @@ private: USRP2_HOST_RX_VRT_TRAILER_WORDS32 - ((2 + 14 + 20 + 8)/sizeof(uint32_t)) //size of headers (pad, eth, ip, udp) ; - uint32_t _tmp_send_mem[_mtu/sizeof(uint32_t)]; - uint32_t _tmp_recv_mem[_mtu/sizeof(uint32_t)]; - uint32_t _spillover_mem[_mtu/sizeof(uint32_t)]; - boost::asio::mutable_buffer _splillover_buff; + static const size_t _tx_vrt_max_offset_words32 = 7; //TODO move to future vrt lib + uint32_t _tx_mem[_mtu/sizeof(uint32_t)]; + boost::asio::const_buffer _tx_copy_buff; + uhd::transport::smart_buffer::sptr _rx_smart_buff; + boost::asio::const_buffer _rx_copy_buff; void io_init(void); //udp transports for control and data - uhd::transport::udp::sptr _ctrl_transport; - uhd::transport::udp::sptr _data_transport; + uhd::transport::udp_simple::sptr _ctrl_transport; + uhd::transport::udp_zero_copy::sptr _data_transport; //private vars for dealing with send/recv control uint32_t _ctrl_seq_num; -- cgit v1.2.3 From bb8417526c14bd49192c159cbdc52f5ea0063784 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 3 Mar 2010 01:19:00 -0800 Subject: Making use of vrt lib in the usrp2 io_impl. Added a packet size param to the vrt pack and unpack. --- host/apps/discover_usrps.cpp | 1 + host/include/uhd/transport/vrt.hpp | 4 ++ host/lib/transport/vrt.cpp | 10 +++- host/lib/usrp/usrp2/dsp_impl.cpp | 2 +- host/lib/usrp/usrp2/io_impl.cpp | 115 ++++++++++++++++--------------------- host/lib/usrp/usrp2/usrp2_impl.cpp | 4 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 17 +++--- host/test/vrt_test.cpp | 3 + 8 files changed, 76 insertions(+), 80 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/apps/discover_usrps.cpp b/host/apps/discover_usrps.cpp index 20ac1f9ed..448095726 100644 --- a/host/apps/discover_usrps.cpp +++ b/host/apps/discover_usrps.cpp @@ -63,6 +63,7 @@ int main(int argc, char *argv[]){ std::cout << "-- USRP Device " << i << std::endl; std::cout << "--------------------------------------------------" << std::endl; std::cout << device_addrs[i] << std::endl << std::endl; + //uhd::device::make(device_addrs[i]); //test make } return 0; diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp index b56da4077..2fb90a497 100644 --- a/host/include/uhd/transport/vrt.hpp +++ b/host/include/uhd/transport/vrt.hpp @@ -33,6 +33,7 @@ namespace vrt{ * \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 num_packet_words32 the length of the packet * \param packet_count the packet count sequence number */ void pack( @@ -40,6 +41,7 @@ namespace vrt{ uint32_t *header_buff, //output size_t &num_header_words32, //output size_t num_payload_words32, //input + size_t &num_packet_words32, //output size_t packet_count //input ); @@ -49,6 +51,7 @@ namespace vrt{ * \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 num_packet_words32 the length of the packet * \param packet_count the packet count sequence number */ void unpack( @@ -56,6 +59,7 @@ namespace vrt{ const uint32_t *header_buff, //input size_t &num_header_words32, //output size_t &num_payload_words32, //output + size_t num_packet_words32, //input size_t &packet_count //output ); diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp index 40b26d31f..19bfc1d19 100644 --- a/host/lib/transport/vrt.cpp +++ b/host/lib/transport/vrt.cpp @@ -26,6 +26,7 @@ void vrt::pack( uint32_t *header_buff, //output size_t &num_header_words32, //output size_t num_payload_words32, //input + size_t &num_packet_words32, //output size_t packet_count //input ){ uint32_t vrt_hdr_flags = 0; @@ -47,10 +48,12 @@ void vrt::pack( vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0; vrt_hdr_flags |= (metadata.end_of_burst)? (0x1 << 24) : 0; + num_packet_words32 = num_header_words32 + num_payload_words32; + //fill in complete header word header_buff[0] = htonl(vrt_hdr_flags | ((packet_count & 0xf) << 16) | - ((num_header_words32 + num_payload_words32) & 0xffff) + (num_packet_words32 & 0xffff) ); } @@ -59,6 +62,7 @@ void vrt::unpack( const uint32_t *header_buff, //input size_t &num_header_words32, //output size_t &num_payload_words32, //output + size_t num_packet_words32, //input size_t &packet_count //output ){ //clear the metadata @@ -70,8 +74,8 @@ void vrt::unpack( 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 (packet_words32 == 0 or num_packet_words32 < packet_words32) + throw std::runtime_error("bad vrt header or packet fragment"); if (vrt_hdr_word & (0x7 << 29)) throw std::runtime_error("unsupported vrt packet type"); diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 8fdfd685f..a32f68872 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -82,7 +82,7 @@ void usrp2_impl::update_ddc_enabled(void){ out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0; out_data.data.streaming.secs = htonl(_ddc_stream_at.secs); out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks); - out_data.data.streaming.samples = htonl(_max_samples_per_packet); + out_data.data.streaming.samples = htonl(_max_rx_samples_per_packet); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 6969e0a89..9299bb04a 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -21,6 +21,7 @@ using namespace uhd; using namespace uhd::usrp; +using namespace uhd::transport; namespace asio = boost::asio; /*********************************************************************** @@ -115,45 +116,6 @@ static inline void usrp2_items_to_host_items( } } -/*********************************************************************** - * Send Raw Data - **********************************************************************/ -size_t usrp2_impl::send_raw(const uhd::metadata_t &metadata){ - size_t num_items = asio::buffer_size(_tx_copy_buff)/sizeof(uint32_t); - const uint32_t *items = asio::buffer_cast(_tx_copy_buff); - - uint32_t vrt_hdr[_tx_vrt_max_offset_words32]; - 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 | - ((_tx_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) | - ((num_vrt_hdr_words + num_items) & 0xffff) - ); - - //copy in the vrt header (yes we left space) - std::memcpy(((uint32_t *)items) - num_vrt_hdr_words, vrt_hdr, num_vrt_hdr_words); - asio::const_buffer buff(items - num_vrt_hdr_words, (num_vrt_hdr_words + num_items)*sizeof(uint32_t)); - - //send and return number of samples - return (_data_transport->send(buff) - num_vrt_hdr_words*sizeof(uint32_t))/sizeof(sc16_t); -} - /*********************************************************************** * Receive Raw Data **********************************************************************/ @@ -161,34 +123,37 @@ void usrp2_impl::recv_raw(uhd::metadata_t &metadata){ //do a receive _rx_smart_buff = _data_transport->recv(); - //////////////////////////////////////////////////////////////////// - // !!!! FIXME this is very flawed, use a proper vrt unpacker !!!!!!! - //////////////////////////////////////////////////////////////////// - //unpack the vrt header const uint32_t *vrt_hdr = asio::buffer_cast(_rx_smart_buff->get()); - 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]); - - 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; + size_t num_packet_words32 = asio::buffer_size(_rx_smart_buff->get())/sizeof(uint32_t); + size_t num_header_words32_out; + size_t num_payload_words32_out; + size_t packet_count_out; + try{ + vrt::unpack( + metadata, //output + vrt_hdr, //input + num_header_words32_out, //output + num_payload_words32_out, //output + num_packet_words32, //input + packet_count_out //output + ); + }catch(const std::exception &e){ + std::cerr << "bad vrt header: " << e.what() << std::endl; + _rx_copy_buff = boost::asio::buffer("", 0); + } - //extract the number of bytes received - size_t num_words = (vrt_header & 0xffff) - - USRP2_HOST_RX_VRT_HEADER_WORDS32 - - USRP2_HOST_RX_VRT_TRAILER_WORDS32; + //handle the packet count / sequence number + size_t last_packet_count = _rx_stream_id_to_packet_seq[metadata.stream_id]; + if (packet_count_out != (last_packet_count+1)%16){ + std::cerr << "bad packet count: " << packet_count_out << std::endl; + } + _rx_stream_id_to_packet_seq[metadata.stream_id] = packet_count_out; //setup the rx buffer to point to the data _rx_copy_buff = boost::asio::buffer( - vrt_hdr + USRP2_HOST_RX_VRT_HEADER_WORDS32, - num_words*sizeof(uint32_t) + vrt_hdr + num_header_words32_out, + num_payload_words32_out*sizeof(uint32_t) ); } @@ -200,8 +165,9 @@ size_t usrp2_impl::send( const uhd::metadata_t &metadata, const std::string &type ){ - uint32_t *items = _tx_mem + _tx_vrt_max_offset_words32; //offset for data - size_t num_samps = _max_samples_per_packet; + uint32_t tx_mem[_mtu/sizeof(uint32_t)]; + uint32_t *items = tx_mem + vrt::max_header_words32; //offset for data + size_t num_samps = _max_tx_samples_per_packet; //calculate the number of samples to be copied //and copy the samples into the send buffer @@ -217,9 +183,26 @@ size_t usrp2_impl::send( throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type)); } - //send the samples (this line seems silly, will be better with vrt lib) - _tx_copy_buff = asio::buffer(items, num_samps*sizeof(uint32_t)); - return send_raw(metadata); //return num_samps; + uint32_t vrt_hdr[vrt::max_header_words32]; + size_t num_header_words32, num_packet_words32; + size_t packet_count = _tx_stream_id_to_packet_seq[metadata.stream_id]++; + + //pack metadata into a vrt header + vrt::pack( + metadata, //input + vrt_hdr, //output + num_header_words32, //output + num_samps, //input + num_packet_words32, //output + packet_count //input + ); + + //copy in the vrt header (yes we left space) + std::memcpy(items - num_header_words32, vrt_hdr, num_header_words32); + asio::const_buffer send_buff(items - num_header_words32, num_packet_words32*sizeof(uint32_t)); + + //send and return number of samples + _data_transport->send(send_buff); return num_samps; } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 51082df15..752feb05b 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -209,11 +209,11 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ return; case DEVICE_PROP_MAX_RX_SAMPLES: - val = size_t(_max_samples_per_packet); + val = size_t(_max_rx_samples_per_packet); return; case DEVICE_PROP_MAX_TX_SAMPLES: - val = size_t(_max_samples_per_packet); + val = size_t(_max_tx_samples_per_packet); return; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index a58bf8471..083ad7096 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -104,20 +105,20 @@ public: private: //the raw io interface (samples are in the usrp2 native format) - size_t send_raw(const uhd::metadata_t &); void recv_raw(uhd::metadata_t &); uhd::dict _tx_stream_id_to_packet_seq; uhd::dict _rx_stream_id_to_packet_seq; static const size_t _mtu = 1500; //FIXME we have no idea - static const size_t _max_samples_per_packet = - _mtu/sizeof(uint32_t) - + static const size_t _hdrs = (2 + 14 + 20 + 8); //size of headers (pad, eth, ip, udp) + static const size_t _max_rx_samples_per_packet = + (_mtu - _hdrs)/sizeof(uint32_t) - USRP2_HOST_RX_VRT_HEADER_WORDS32 - - USRP2_HOST_RX_VRT_TRAILER_WORDS32 - - ((2 + 14 + 20 + 8)/sizeof(uint32_t)) //size of headers (pad, eth, ip, udp) + USRP2_HOST_RX_VRT_TRAILER_WORDS32 + ; + static const size_t _max_tx_samples_per_packet = + (_mtu - _hdrs)/sizeof(uint32_t) - + uhd::transport::vrt::max_header_words32 ; - static const size_t _tx_vrt_max_offset_words32 = 7; //TODO move to future vrt lib - uint32_t _tx_mem[_mtu/sizeof(uint32_t)]; - boost::asio::const_buffer _tx_copy_buff; uhd::transport::smart_buffer::sptr _rx_smart_buff; boost::asio::const_buffer _rx_copy_buff; void io_init(void); diff --git a/host/test/vrt_test.cpp b/host/test/vrt_test.cpp index 9b2d43430..a4fad78fc 100644 --- a/host/test/vrt_test.cpp +++ b/host/test/vrt_test.cpp @@ -27,6 +27,7 @@ static void pack_and_unpack( ){ uint32_t header_buff[vrt::max_header_words32]; size_t num_header_words32; + size_t num_packet_words32; //pack metadata into a vrt header vrt::pack( @@ -34,6 +35,7 @@ static void pack_and_unpack( header_buff, //output num_header_words32, //output num_payload_words32, //input + num_packet_words32, //output packet_count //input ); @@ -48,6 +50,7 @@ static void pack_and_unpack( header_buff, //input num_header_words32_out, //output num_payload_words32_out, //output + num_packet_words32, //input packet_count_out //output ); -- cgit v1.2.3 From e531f936e6ffa645a944b360a51f82004c6cdfcb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 3 Mar 2010 02:00:00 -0800 Subject: memcpy size fix, change to some send logic --- host/lib/usrp/usrp2/io_impl.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 9299bb04a..642b6b08b 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -198,11 +198,12 @@ size_t usrp2_impl::send( ); //copy in the vrt header (yes we left space) - std::memcpy(items - num_header_words32, vrt_hdr, num_header_words32); - asio::const_buffer send_buff(items - num_header_words32, num_packet_words32*sizeof(uint32_t)); + items -= num_header_words32; + std::memcpy(items, vrt_hdr, num_header_words32*sizeof(uint32_t)); //send and return number of samples - _data_transport->send(send_buff); return num_samps; + _data_transport->send(asio::buffer(items, num_packet_words32*sizeof(uint32_t))); + return num_samps; } /*********************************************************************** -- cgit v1.2.3 From ccd2665a29af046b0b8a11c48ffbfe2ed36ce8d9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 3 Mar 2010 11:28:32 -0800 Subject: Split metadata into rx and tx specific metadata. The rx metadata has fragment flags and the tx metatdata has burst flags. Made the io impl for usrp2 rx routine fill in the rx metatdata fragment flag. Added device documentation for send and recv in regards to fragmentation. --- host/include/uhd/device.hpp | 21 +++++++++++++++++++-- host/include/uhd/metadata.hpp | 31 ++++++++++++++++++++----------- host/include/uhd/transport/vrt.hpp | 14 +++++++------- host/lib/CMakeLists.txt | 1 + host/lib/metadata.cpp | 37 +++++++++++++++++++++++++++++++++++++ host/lib/transport/vrt.cpp | 16 ++++++++-------- host/lib/usrp/usrp2/io_impl.cpp | 20 +++++++++++++------- host/lib/usrp/usrp2/usrp2_impl.hpp | 6 +++--- host/test/vrt_test.cpp | 12 ++++++------ 9 files changed, 114 insertions(+), 44 deletions(-) create mode 100644 host/lib/metadata.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index ba5337d33..1a52867c9 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -70,6 +70,13 @@ public: /*! * Send a buffer containing IF data with its metadata. * + * Send handles fragmentation as follows: + * If the buffer has more samples than the maximum supported, + * the send method will send the maximum number of samples + * as supported by the transport and return the number sent. + * It is up to the caller to call send again on the un-sent + * portions of the buffer, until the buffer is exhausted. + * * \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) @@ -77,13 +84,23 @@ public: */ virtual size_t send( const boost::asio::const_buffer &buff, - const metadata_t &metadata, + const tx_metadata_t &metadata, const std::string &type = "32fc" ) = 0; /*! * Receive a buffer containing IF data and its metadata. * + * Receive handles fragmentation as follows: + * If the buffer has insufficient space to hold all samples + * that were received in a single packet over-the-wire, + * then the buffer will be completely filled and the implementation + * will hold a pointer into the remaining portion of the packet. + * Subsequent calls will load from the remainder of the packet, + * and will flag the metadata to show that this is a fragment. + * The next call to receive, after the remainder becomes exahausted, + * will perform an over-the-wire receive as usual. + * * \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) @@ -91,7 +108,7 @@ public: */ virtual size_t recv( const boost::asio::mutable_buffer &buff, - metadata_t &metadata, + rx_metadata_t &metadata, const std::string &type = "32fc" ) = 0; }; diff --git a/host/include/uhd/metadata.hpp b/host/include/uhd/metadata.hpp index 70842e7bc..0588ef0ed 100644 --- a/host/include/uhd/metadata.hpp +++ b/host/include/uhd/metadata.hpp @@ -23,12 +23,27 @@ namespace uhd{ /*! - * Metadata structure for describing the IF data. - * Includes stream ID, time specification, and burst flags. + * RX metadata structure for describing sent IF data. + * Includes stream ID, time specification, and fragmentation flags. * The receive routines will convert IF data headers into metadata. + */ +struct rx_metadata_t{ + uint32_t stream_id; + bool has_stream_id; + time_spec_t time_spec; + bool has_time_spec; + bool is_fragment; + + //default constructor + rx_metadata_t(void); +}; + +/*! + * TX metadata structure for describing received IF data. + * Includes stream ID, time specification, and burst flags. * The send routines will convert the metadata to IF data headers. */ -struct metadata_t{ +struct tx_metadata_t{ uint32_t stream_id; bool has_stream_id; time_spec_t time_spec; @@ -36,14 +51,8 @@ struct metadata_t{ bool start_of_burst; bool end_of_burst; - metadata_t(void){ - stream_id = 0; - has_stream_id = false; - time_spec = time_spec_t(); - has_time_spec = false; - start_of_burst = false; - end_of_burst = false; - } + //default constructor + tx_metadata_t(void); }; } //namespace uhd diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp index 2fb90a497..1700d2785 100644 --- a/host/include/uhd/transport/vrt.hpp +++ b/host/include/uhd/transport/vrt.hpp @@ -37,12 +37,12 @@ namespace vrt{ * \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 &num_packet_words32, //output - size_t packet_count //input + const tx_metadata_t &metadata, //input + uint32_t *header_buff, //output + size_t &num_header_words32, //output + size_t num_payload_words32, //input + size_t &num_packet_words32, //output + size_t packet_count //input ); /*! @@ -55,7 +55,7 @@ namespace vrt{ * \param packet_count the packet count sequence number */ void unpack( - metadata_t &metadata, //output + rx_metadata_t &metadata, //output const uint32_t *header_buff, //input size_t &num_header_words32, //output size_t &num_payload_words32, //output diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 390349906..b1daf22d1 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -22,6 +22,7 @@ SET(libuhd_sources device.cpp device_addr.cpp gain_handler.cpp + metadata.cpp wax.cpp transport/udp_simple.cpp transport/vrt.cpp diff --git a/host/lib/metadata.cpp b/host/lib/metadata.cpp new file mode 100644 index 000000000..40fdb7c73 --- /dev/null +++ b/host/lib/metadata.cpp @@ -0,0 +1,37 @@ +// +// 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 . +// + +#include + +using namespace uhd; + +rx_metadata_t::rx_metadata_t(void){ + stream_id = 0; + has_stream_id = false; + time_spec = time_spec_t(); + has_time_spec = false; + is_fragment = false; +} + +tx_metadata_t::tx_metadata_t(void){ + stream_id = 0; + has_stream_id = false; + time_spec = time_spec_t(); + has_time_spec = false; + start_of_burst = false; + end_of_burst = false; +} diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp index 19bfc1d19..5029df217 100644 --- a/host/lib/transport/vrt.cpp +++ b/host/lib/transport/vrt.cpp @@ -22,12 +22,12 @@ 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 &num_packet_words32, //output - size_t packet_count //input + const tx_metadata_t &metadata, //input + uint32_t *header_buff, //output + size_t &num_header_words32, //output + size_t num_payload_words32, //input + size_t &num_packet_words32, //output + size_t packet_count //input ){ uint32_t vrt_hdr_flags = 0; num_header_words32 = 1; @@ -58,7 +58,7 @@ void vrt::pack( } void vrt::unpack( - metadata_t &metadata, //output + rx_metadata_t &metadata, //output const uint32_t *header_buff, //input size_t &num_header_words32, //output size_t &num_payload_words32, //output @@ -66,7 +66,7 @@ void vrt::unpack( size_t &packet_count //output ){ //clear the metadata - metadata = metadata_t(); + metadata = rx_metadata_t(); //extract vrt header uint32_t vrt_hdr_word = ntohl(header_buff[0]); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 642b6b08b..5529cfe57 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -119,7 +119,7 @@ static inline void usrp2_items_to_host_items( /*********************************************************************** * Receive Raw Data **********************************************************************/ -void usrp2_impl::recv_raw(uhd::metadata_t &metadata){ +void usrp2_impl::recv_raw(rx_metadata_t &metadata){ //do a receive _rx_smart_buff = _data_transport->recv(); @@ -161,8 +161,8 @@ void usrp2_impl::recv_raw(uhd::metadata_t &metadata){ * Send Data **********************************************************************/ size_t usrp2_impl::send( - const boost::asio::const_buffer &buff, - const uhd::metadata_t &metadata, + const asio::const_buffer &buff, + const tx_metadata_t &metadata, const std::string &type ){ uint32_t tx_mem[_mtu/sizeof(uint32_t)]; @@ -210,13 +210,19 @@ size_t usrp2_impl::send( * Receive Data **********************************************************************/ size_t usrp2_impl::recv( - const boost::asio::mutable_buffer &buff, - uhd::metadata_t &metadata, + const asio::mutable_buffer &buff, + rx_metadata_t &metadata, const std::string &type ){ //perform a receive if no rx data is waiting to be copied - if (asio::buffer_size(_rx_copy_buff) == 0) recv_raw(metadata); - //TODO otherwise flag the metadata to show that is is a fragment + if (asio::buffer_size(_rx_copy_buff) == 0){ + recv_raw(metadata); + } + //otherwise flag the metadata to show that is is a fragment + else{ + metadata = rx_metadata_t(); + metadata.is_fragment = true; + } //extract the number of samples available to copy //and a pointer into the usrp2 received items memory diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 083ad7096..f4e6054bd 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -100,12 +100,12 @@ public: double get_master_clock_freq(void); //the io interface - 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 &); + size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &); + size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &); private: //the raw io interface (samples are in the usrp2 native format) - void recv_raw(uhd::metadata_t &); + void recv_raw(uhd::rx_metadata_t &); uhd::dict _tx_stream_id_to_packet_seq; uhd::dict _rx_stream_id_to_packet_seq; static const size_t _mtu = 1500; //FIXME we have no idea diff --git a/host/test/vrt_test.cpp b/host/test/vrt_test.cpp index a4fad78fc..d80908c74 100644 --- a/host/test/vrt_test.cpp +++ b/host/test/vrt_test.cpp @@ -21,7 +21,7 @@ using namespace uhd::transport; static void pack_and_unpack( - const uhd::metadata_t &metadata, + const uhd::tx_metadata_t &metadata, size_t num_payload_words32, size_t packet_count ){ @@ -39,7 +39,7 @@ static void pack_and_unpack( packet_count //input ); - uhd::metadata_t metadata_out; + uhd::rx_metadata_t metadata_out; size_t num_header_words32_out; size_t num_payload_words32_out; size_t packet_count_out; @@ -70,19 +70,19 @@ static void pack_and_unpack( } BOOST_AUTO_TEST_CASE(test_with_none){ - uhd::metadata_t metadata; + uhd::tx_metadata_t metadata; pack_and_unpack(metadata, 300, 1); } BOOST_AUTO_TEST_CASE(test_with_sid){ - uhd::metadata_t metadata; + uhd::tx_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; + uhd::tx_metadata_t metadata; metadata.has_time_spec = true; metadata.time_spec.secs = 7; metadata.time_spec.ticks = 2000; @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(test_with_time_spec){ } BOOST_AUTO_TEST_CASE(test_with_sid_and_time_spec){ - uhd::metadata_t metadata; + uhd::tx_metadata_t metadata; metadata.has_stream_id = true; metadata.stream_id = 2; metadata.has_time_spec = true; -- cgit v1.2.3 From 821c31417894bed5603dc1a18415d4a35ddd7c2d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 3 Mar 2010 12:30:44 -0800 Subject: Some tweaks and changes to io impl that fix segfaults. Seems to work now! --- host/lib/usrp/usrp2/io_impl.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 5529cfe57..6273846dc 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -124,8 +124,12 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ _rx_smart_buff = _data_transport->recv(); //unpack the vrt header - const uint32_t *vrt_hdr = asio::buffer_cast(_rx_smart_buff->get()); size_t num_packet_words32 = asio::buffer_size(_rx_smart_buff->get())/sizeof(uint32_t); + if (num_packet_words32 == 0){ + _rx_copy_buff = boost::asio::buffer("", 0); + return; //must exit here after setting the buffer + } + const uint32_t *vrt_hdr = asio::buffer_cast(_rx_smart_buff->get()); size_t num_header_words32_out; size_t num_payload_words32_out; size_t packet_count_out; @@ -141,17 +145,18 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ }catch(const std::exception &e){ std::cerr << "bad vrt header: " << e.what() << std::endl; _rx_copy_buff = boost::asio::buffer("", 0); + return; //must exit here after setting the buffer } //handle the packet count / sequence number - size_t last_packet_count = _rx_stream_id_to_packet_seq[metadata.stream_id]; - if (packet_count_out != (last_packet_count+1)%16){ + size_t expected_packet_count = _rx_stream_id_to_packet_seq[metadata.stream_id]; + if (packet_count_out != expected_packet_count){ std::cerr << "bad packet count: " << packet_count_out << std::endl; } - _rx_stream_id_to_packet_seq[metadata.stream_id] = packet_count_out; + _rx_stream_id_to_packet_seq[metadata.stream_id] = (packet_count_out+1)%16; //setup the rx buffer to point to the data - _rx_copy_buff = boost::asio::buffer( + _rx_copy_buff = asio::buffer( vrt_hdr + num_header_words32_out, num_payload_words32_out*sizeof(uint32_t) ); @@ -226,7 +231,9 @@ size_t usrp2_impl::recv( //extract the number of samples available to copy //and a pointer into the usrp2 received items memory - size_t num_samps = asio::buffer_size(_rx_copy_buff)/sizeof(uint32_t); + size_t bytes_to_copy = asio::buffer_size(_rx_copy_buff); + if (bytes_to_copy == 0) return 0; //nothing to receive + size_t num_samps = bytes_to_copy/sizeof(uint32_t); const uint32_t *items = asio::buffer_cast(_rx_copy_buff); //calculate the number of samples to be copied @@ -244,7 +251,9 @@ size_t usrp2_impl::recv( } //update the rx copy buffer to reflect the bytes copied - _rx_copy_buff = asio::buffer(items + num_samps, num_samps*sizeof(uint32_t)); + _rx_copy_buff = asio::buffer( + items + num_samps, bytes_to_copy - num_samps*sizeof(uint32_t) + ); return num_samps; } -- cgit v1.2.3 From bb86022d5a5f7055cdeebaeb4a55216e1a056fd4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 4 Mar 2010 18:34:28 -0800 Subject: Moved timeouts into the udp transports. Simplified the fast path checking in the fw, but it turns out this was not the issue. Fixed some bad bit operations with the 16sc words (dont forget sign extension). Added some more documentation to the headers.... --- firmware/microblaze/apps/txrx.c | 16 ++++++++---- firmware/microblaze/lib/net_common.c | 11 -------- firmware/microblaze/lib/net_common.h | 2 -- host/include/uhd/device.hpp | 11 ++++++++ host/include/uhd/transport/udp_simple.hpp | 4 +-- host/include/uhd/transport/udp_zero_copy.hpp | 4 +-- host/lib/transport/udp_simple.cpp | 29 +++++++++++++++++++-- host/lib/transport/udp_zero_copy_none.cpp | 39 ++++++++++++++++++++++++++-- host/lib/usrp/usrp2/dsp_impl.cpp | 9 ++++--- host/lib/usrp/usrp2/io_impl.cpp | 14 +++++----- host/lib/usrp/usrp2/usrp2_impl.cpp | 39 ++++++++++------------------ 11 files changed, 115 insertions(+), 63 deletions(-) (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 9c3caa4f2..1b3299150 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -504,16 +504,22 @@ void handle_udp_ctrl_packet( static bool eth_pkt_inspector(dbsm_t *sm, int bufno) { - //extract buffer point and length + //point me to the ethernet frame uint32_t *buff = (uint32_t *)buffer_ram(bufno); - size_t len = buffer_pool_status->last_line[bufno] - 3; //treat this as fast-path data? - if (is_udp_packet_with_vrt(buff, len, USRP2_UDP_DATA_PORT)){ - return false; - } + // We have to do this operation as fast as possible. + // Therefore, we do not check all the headers, + // just check that the udp port matches + // and that the vrt header is non zero. + // In the future, a hardware state machine will do this... + if ( //warning! magic numbers approaching.... + (((buff + ((2 + 14 + 20)/sizeof(uint32_t)))[0] & 0xffff) == USRP2_UDP_DATA_PORT) && + ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[0] != 0) + ) return false; //pass it to the slow-path handler + size_t len = buffer_pool_status->last_line[bufno] - 3; handle_eth_packet(buff, len); return true; } diff --git a/firmware/microblaze/lib/net_common.c b/firmware/microblaze/lib/net_common.c index ab7aadca9..693502d18 100644 --- a/firmware/microblaze/lib/net_common.c +++ b/firmware/microblaze/lib/net_common.c @@ -378,17 +378,6 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size) } } -bool is_udp_packet_with_vrt(uint32_t *p, size_t nlines, int port){ - struct ip_hdr *ip = (struct ip_hdr *)(p + 4); - struct udp_hdr *udp = (struct udp_hdr *)(((char *)ip) + IP_HLEN); - uint32_t *payload = (uint32_t *)(((char *)udp) + UDP_HLEN); - return \ - (p[3] & 0xffff) == ETHERTYPE_IPV4 && - IPH_PROTO(ip) == IP_PROTO_UDP && - udp->dest == port && - payload[0] != 0; //must be non zero vrt header -} - void handle_eth_packet(uint32_t *p, size_t nlines) { diff --git a/firmware/microblaze/lib/net_common.h b/firmware/microblaze/lib/net_common.h index 1a7052f71..6cd45bf69 100644 --- a/firmware/microblaze/lib/net_common.h +++ b/firmware/microblaze/lib/net_common.h @@ -56,6 +56,4 @@ void send_udp_pkt(int src_port, struct socket_address dst, void handle_eth_packet(uint32_t *p, size_t nlines); -bool is_udp_packet_with_vrt(uint32_t *p, size_t nlines, int port); - #endif /* INCLUDED_NET_COMMON_H */ diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 1a52867c9..47dfa4328 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -77,6 +77,9 @@ public: * It is up to the caller to call send again on the un-sent * portions of the buffer, until the buffer is exhausted. * + * This is a blocking call and will not return until the number + * of samples returned have been read out of the buffer. + * * \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) @@ -101,6 +104,14 @@ public: * The next call to receive, after the remainder becomes exahausted, * will perform an over-the-wire receive as usual. * + * This is a blocking call and will not return until the number + * of samples returned have been written into the buffer. + * However, a call to receive may timeout and return zero samples. + * The timeout duration is decided by the underlying transport layer. + * The caller should assume that the call to receive will not return + * immediately when no packets are available to the transport layer, + * and that the timeout duration is reasonably tuned for performance. + * * \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) diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp index 8663128ec..0d8fcc5f0 100644 --- a/host/include/uhd/transport/udp_simple.hpp +++ b/host/include/uhd/transport/udp_simple.hpp @@ -67,9 +67,9 @@ public: /*! * Receive into the provided buffer. - * Returns empty when data is not available. + * Blocks until data is received or a timeout occurs. * \param buff a mutable buffer to receive into - * \return the number of bytes received. + * \return the number of bytes received or zero on timeout */ virtual size_t recv(const boost::asio::mutable_buffer &buff) = 0; }; diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp index 9c3505dd6..1a8d822fd 100644 --- a/host/include/uhd/transport/udp_zero_copy.hpp +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -64,9 +64,9 @@ public: /*! * Receive a buffer. + * Blocks until data is received or a timeout occurs. * The memory is managed by the implementation. - * Returns an empty buffer when data is not available. - * \return a smart buffer with memory and size + * \return a smart buffer (empty on timeout) */ virtual smart_buffer::sptr recv(void) = 0; }; diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp index 491cf59db..7004bdfdf 100644 --- a/host/lib/transport/udp_simple.cpp +++ b/host/lib/transport/udp_simple.cpp @@ -16,11 +16,34 @@ // #include +#include #include #include using namespace uhd::transport; +/*********************************************************************** + * Helper Functions + **********************************************************************/ +/*! + * A receive timeout for a socket: + * + * It seems that asio cannot have timeouts with synchronous io. + * However, we can implement a polling loop that will timeout. + * This is okay bacause this is the slow-path implementation. + * + * \param socket the asio socket + */ +static void reasonable_recv_timeout( + boost::asio::ip::udp::socket &socket +){ + boost::asio::deadline_timer timer(socket.get_io_service()); + timer.expires_from_now(boost::posix_time::milliseconds(50)); + while (not (socket.available() or timer.expires_from_now().is_negative())){ + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } +} + /*********************************************************************** * UDP connected implementation class **********************************************************************/ @@ -62,7 +85,8 @@ size_t udp_connected_impl::send(const boost::asio::const_buffer &buff){ } size_t udp_connected_impl::recv(const boost::asio::mutable_buffer &buff){ - if (_socket->available() == 0) return 0; + reasonable_recv_timeout(*_socket); + if (not _socket->available()) return 0; return _socket->receive(boost::asio::buffer(buff)); } @@ -112,7 +136,8 @@ size_t udp_broadcast_impl::send(const boost::asio::const_buffer &buff){ } size_t udp_broadcast_impl::recv(const boost::asio::mutable_buffer &buff){ - if (_socket->available() == 0) return 0; + reasonable_recv_timeout(*_socket); + if (not _socket->available()) return 0; boost::asio::ip::udp::endpoint sender_endpoint; return _socket->receive_from(boost::asio::buffer(buff), sender_endpoint); } diff --git a/host/lib/transport/udp_zero_copy_none.cpp b/host/lib/transport/udp_zero_copy_none.cpp index e95706d94..e29530cf1 100644 --- a/host/lib/transport/udp_zero_copy_none.cpp +++ b/host/lib/transport/udp_zero_copy_none.cpp @@ -16,6 +16,8 @@ // #include +#include +#include using namespace uhd::transport; @@ -67,6 +69,9 @@ public: private: boost::asio::ip::udp::socket *_socket; boost::asio::io_service _io_service; + + size_t get_recv_buff_size(void); + void set_recv_buff_size(size_t); }; udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ @@ -81,6 +86,18 @@ udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::strin _socket = new boost::asio::ip::udp::socket(_io_service); _socket->open(boost::asio::ip::udp::v4()); _socket->connect(receiver_endpoint); + + // set the rx socket buffer size: + // pick a huge size, and deal with whatever we get + set_recv_buff_size(54321e3); //some big number! + size_t current_buff_size = get_recv_buff_size(); + std::cout << boost::format( + "Current rx socket buffer size: %d\n" + ) % current_buff_size; + if (current_buff_size < .1e6) std::cout << boost::format( + "Adjust max rx socket buffer size (linux only):\n" + " sysctl -w net.core.rmem_max=VALUE\n" + ); } udp_zero_copy_impl::~udp_zero_copy_impl(void){ @@ -92,14 +109,21 @@ size_t udp_zero_copy_impl::send(const boost::asio::const_buffer &buff){ } smart_buffer::sptr udp_zero_copy_impl::recv(void){ - size_t available = _socket->available(); + size_t available = 0; + + //implement timeout through polling and sleeping + boost::asio::deadline_timer timer(_socket->get_io_service()); + timer.expires_from_now(boost::posix_time::milliseconds(50)); + while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){ + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } //allocate memory and create buffer uint32_t *buff_mem = new uint32_t[available/sizeof(uint32_t)]; boost::asio::mutable_buffer buff(buff_mem, available); //receive only if data is available - if (available > 0){ + if (available){ _socket->receive(boost::asio::buffer(buff)); } @@ -107,6 +131,17 @@ smart_buffer::sptr udp_zero_copy_impl::recv(void){ return smart_buffer::sptr(new smart_buffer_impl(buff)); } +size_t udp_zero_copy_impl::get_recv_buff_size(void){ + boost::asio::socket_base::receive_buffer_size option; + _socket->get_option(option); + return option.value(); +} + +void udp_zero_copy_impl::set_recv_buff_size(size_t new_size){ + boost::asio::socket_base::receive_buffer_size option(new_size); + _socket->set_option(option); +} + /*********************************************************************** * UDP zero copy make function **********************************************************************/ diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index a32f68872..7831b7667 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -21,6 +21,9 @@ using namespace uhd; +static const size_t default_decim = 16; +static const size_t default_interp = 16; + /*********************************************************************** * DDC Helper Methods **********************************************************************/ @@ -37,7 +40,7 @@ static uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t } static uint32_t calculate_iq_scale_word(int16_t i, int16_t q){ - return ((i & 0xffff) << 16) | ((q & 0xffff) << 0); + return (uint16_t(i) << 16) | (uint16_t(q) << 0); } void usrp2_impl::init_ddc_config(void){ @@ -48,7 +51,7 @@ void usrp2_impl::init_ddc_config(void){ ); //initial config and update - _ddc_decim = 64; + _ddc_decim = default_decim; _ddc_freq = 0; update_ddc_config(); @@ -196,7 +199,7 @@ void usrp2_impl::init_duc_config(void){ ); //initial config and update - _duc_interp = 64; + _duc_interp = default_interp; _duc_freq = 0; update_duc_config(); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 6273846dc..cc7746720 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -71,9 +71,9 @@ static inline void host_floats_to_usrp2_items( size_t num_samps ){ 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)); + uint16_t real = host_floats[i].real()*shorts_per_float; + uint16_t imag = host_floats[i].imag()*shorts_per_float; + usrp2_items[i] = htonl((real << 16) | (imag << 0)); }); } @@ -84,8 +84,8 @@ static inline void usrp2_items_to_host_floats( ){ unrolled_loop(i, num_samps,{ uint32_t item = ntohl(usrp2_items[i]); - int16_t real = (item >> 16) & 0xffff; - int16_t imag = (item >> 0) & 0xffff; + int16_t real = item >> 16; + int16_t imag = item >> 0; host_floats[i] = fc32_t(real*floats_per_short, imag*floats_per_short); }); } @@ -130,9 +130,7 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ return; //must exit here after setting the buffer } const uint32_t *vrt_hdr = asio::buffer_cast(_rx_smart_buff->get()); - size_t num_header_words32_out; - size_t num_payload_words32_out; - size_t packet_count_out; + size_t num_header_words32_out, num_payload_words32_out, packet_count_out; try{ vrt::unpack( metadata, //output diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 752feb05b..58c82303f 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -24,6 +24,7 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; +namespace asio = boost::asio; /*********************************************************************** * Discovery over the udp transport @@ -43,19 +44,12 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ ctrl_data_out.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); - //loop and recieve until the time is up - size_t num_timeouts = 0; + //loop and recieve until the timeout while(true){ usrp2_ctrl_data_t ctrl_data_in; - size_t len = udp_transport->recv( - boost::asio::buffer(&ctrl_data_in, sizeof(ctrl_data_in)) - ); + size_t len = udp_transport->recv(asio::buffer(&ctrl_data_in, sizeof(ctrl_data_in))); //std::cout << len << "\n"; - if (len < sizeof(usrp2_ctrl_data_t)){ - //sleep a little so we dont burn cpu - if (num_timeouts++ > 50) break; - boost::this_thread::sleep(boost::posix_time::milliseconds(1)); - }else{ + if (len >= sizeof(usrp2_ctrl_data_t)){ //handle the received data switch(ntohl(ctrl_data_in.id)){ case USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE: @@ -67,9 +61,11 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ new_addr["transport"] = "udp"; new_addr["addr"] = ip_addr.to_string(); usrp2_addrs.push_back(new_addr); - break; + //dont break here, it will exit the while loop + //just continue on to the next loop iteration } } + if (len == 0) break; //timeout } return usrp2_addrs; @@ -164,24 +160,15 @@ usrp2_ctrl_data_t usrp2_impl::ctrl_send_and_recv(const usrp2_ctrl_data_t &out_da out_copy.seq = htonl(++_ctrl_seq_num); _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t))); - //loop and recieve until the time is up - size_t num_timeouts = 0; + //loop until we get the packet or timeout while(true){ usrp2_ctrl_data_t in_data; - size_t len = _ctrl_transport->recv( - boost::asio::buffer(&in_data, sizeof(in_data)) - ); - if (len < sizeof(usrp2_ctrl_data_t)){ - //sleep a little so we dont burn cpu - if (num_timeouts++ > 50) break; - boost::this_thread::sleep(boost::posix_time::milliseconds(1)); - }else{ - //handle the received data - if (ntohl(in_data.seq) == _ctrl_seq_num){ - return in_data; - } - //didnt get seq, continue on... + size_t len = _ctrl_transport->recv(asio::buffer(&in_data, sizeof(in_data))); + if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(in_data.seq) == _ctrl_seq_num){ + return in_data; } + if (len == 0) break; //timeout + //didnt get seq or bad packet, continue looking... } throw std::runtime_error("usrp2 no control response"); } -- cgit v1.2.3 From 8e9a8464386db03a596e0b88d0714d22723d37d0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 10 Mar 2010 14:47:03 -0800 Subject: Added simple device to handle wrapping general properties up into simple api. Added setting time capability to the usrp2 impl. Messing with props and time specs... --- firmware/microblaze/apps/txrx.c | 10 ++ host/apps/discover_usrps.cpp | 2 +- host/include/uhd/CMakeLists.txt | 1 + host/include/uhd/props.hpp | 20 +-- host/include/uhd/simple_device.hpp | 111 +++++++++++++ host/include/uhd/time_spec.hpp | 19 ++- host/include/uhd/utils.hpp | 105 ++++++------- host/lib/CMakeLists.txt | 2 + host/lib/simple_device.cpp | 303 ++++++++++++++++++++++++++++++++++++ host/lib/time_spec.cpp | 40 +++++ host/lib/usrp/usrp2/dboard_impl.cpp | 9 +- host/lib/usrp/usrp2/dsp_impl.cpp | 21 +-- host/lib/usrp/usrp2/fw_common.h | 8 + host/lib/usrp/usrp2/mboard_impl.cpp | 35 ++++- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 + 15 files changed, 591 insertions(+), 96 deletions(-) create mode 100644 host/include/uhd/simple_device.hpp create mode 100644 host/lib/simple_device.cpp create mode 100644 host/lib/time_spec.cpp (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 1b3299150..18bbdd23d 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -489,6 +489,16 @@ void handle_udp_ctrl_packet( ctrl_data_out.id = USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE; break; + /******************************************************************* + * Time Config + ******************************************************************/ + case USRP2_CTRL_ID_GOT_A_NEW_TIME_FOR_YOU_BRO: + sr_time64->imm = (ctrl_data_in->data.time_args.now == 0)? 0 : 1; + sr_time64->ticks = ctrl_data_in->data.time_args.ticks; + sr_time64->secs = ctrl_data_in->data.time_args.secs; //set this last to latch the regs + ctrl_data_out.id = USRP2_CTRL_ID_SWEET_I_GOT_THAT_TIME_DUDE; + break; + default: ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; diff --git a/host/apps/discover_usrps.cpp b/host/apps/discover_usrps.cpp index 448095726..d670d1651 100644 --- a/host/apps/discover_usrps.cpp +++ b/host/apps/discover_usrps.cpp @@ -63,7 +63,7 @@ int main(int argc, char *argv[]){ std::cout << "-- USRP Device " << i << std::endl; std::cout << "--------------------------------------------------" << std::endl; std::cout << device_addrs[i] << std::endl << std::endl; - //uhd::device::make(device_addrs[i]); //test make + uhd::device::make(device_addrs[i]); //test make } return 0; diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index f4fb96786..522f43afd 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -26,6 +26,7 @@ INSTALL(FILES gain_handler.hpp metadata.hpp props.hpp + simple_device.hpp time_spec.hpp utils.hpp wax.hpp diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index cf301d4bd..dea2baf52 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -116,16 +116,16 @@ namespace uhd{ enum dboard_prop_t{ DBOARD_PROP_NAME, //ro, std::string DBOARD_PROP_SUBDEV, //ro, wax::obj - DBOARD_PROP_SUBDEV_NAMES, //ro, prop_names_t - DBOARD_PROP_CODEC //ro, wax::obj - }; + DBOARD_PROP_SUBDEV_NAMES //ro, prop_names_t + //DBOARD_PROP_CODEC //ro, wax::obj //----> not sure, dont have to deal with yet + }; - /*! + /*! ------ not dealing with yet, commented out ------------ * Possible device codec properties: * A codec is expected to have a rate and gain elements. * Other properties can be discovered through the others prop. */ - enum codec_prop_t{ + /*enum codec_prop_t{ CODEC_PROP_NAME, //ro, std::string CODEC_PROP_OTHERS, //ro, prop_names_t CODEC_PROP_GAIN, //rw, gain_t @@ -133,8 +133,8 @@ namespace uhd{ CODEC_PROP_GAIN_MIN, //ro, gain_t CODEC_PROP_GAIN_STEP, //ro, gain_t CODEC_PROP_GAIN_NAMES, //ro, prop_names_t - CODEC_PROP_CLOCK_RATE //ro, freq_t - }; + //CODEC_PROP_CLOCK_RATE //ro, freq_t //----> not sure we care to know + };*/ /*! * Possible device subdev properties @@ -156,9 +156,9 @@ namespace uhd{ SUBDEV_PROP_QUADRATURE, //ro, bool SUBDEV_PROP_IQ_SWAPPED, //ro, bool SUBDEV_PROP_SPECTRUM_INVERTED, //ro, bool - SUBDEV_PROP_IS_TX, //ro, bool - SUBDEV_PROP_RSSI, //ro, gain_t - SUBDEV_PROP_BANDWIDTH //rw, freq_t + SUBDEV_PROP_LO_INTERFERES //ro, bool + //SUBDEV_PROP_RSSI, //ro, gain_t //----> not on all boards, use named prop + //SUBDEV_PROP_BANDWIDTH //rw, freq_t //----> not on all boards, use named prop }; } //namespace uhd diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp new file mode 100644 index 000000000..64ec85a5c --- /dev/null +++ b/host/include/uhd/simple_device.hpp @@ -0,0 +1,111 @@ +// +// 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 . +// + +#include +#include +#include +#include + +#ifndef INCLUDED_UHD_SIMPLE_DEVICE_HPP +#define INCLUDED_UHD_SIMPLE_DEVICE_HPP + +namespace uhd{ + +/*! + * The tune result struct holds result of a 2-phase tuning: + * The struct hold the result of tuning the dboard as + * the target and actual intermediate frequency. + * The struct hold the result of tuning the DDC/DUC as + * the target and actual digital converter frequency. + * It also tell us weather or not the spectrum is inverted. + */ +struct tune_result_t{ + double target_inter_freq; + double actual_inter_freq; + double target_dxc_freq; + double actual_dxc_freq; + bool spectrum_inverted; + tune_result_t(void); +}; + +/*! + * The simple UHD device class: + * A simple device facilitates ease-of-use for most use-case scenarios. + * The wrapper provides convenience functions to tune the devices + * as well as to set the dboard gains, antennas, and other properties. + */ +class simple_device : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + static sptr make(const std::string &args); + + virtual device::sptr get_device(void) = 0; + + virtual std::string get_name(void) = 0; + + /******************************************************************* + * Streaming + ******************************************************************/ + virtual void set_streaming(bool enb) = 0; + virtual bool get_streaming(void) = 0; + + /******************************************************************* + * RX methods + ******************************************************************/ + virtual void set_rx_rate(double rate) = 0; + virtual double get_rx_rate(void) = 0; + virtual std::vector get_rx_rates(void) = 0; + + virtual tune_result_t set_rx_freq(double target_freq, double lo_offset) = 0; + virtual double get_rx_freq_min(void) = 0; + virtual double get_rx_freq_max(void) = 0; + + virtual void set_rx_gain(float gain) = 0; + virtual float get_rx_gain(void) = 0; + virtual float get_rx_gain_min(void) = 0; + virtual float get_rx_gain_max(void) = 0; + virtual float get_rx_gain_step(void) = 0; + + virtual void set_rx_antenna(const std::string &ant) = 0; + virtual std::string get_rx_antenna(void) = 0; + virtual std::vector get_rx_antennas(void) = 0; + + /******************************************************************* + * TX methods + ******************************************************************/ + virtual void set_tx_rate(double rate) = 0; + virtual double get_tx_rate(void) = 0; + virtual std::vector get_tx_rates(void) = 0; + + virtual tune_result_t set_tx_freq(double target_freq, double lo_offset) = 0; + virtual double get_tx_freq_min(void) = 0; + virtual double get_tx_freq_max(void) = 0; + + virtual void set_tx_gain(float gain) = 0; + virtual float get_tx_gain(void) = 0; + virtual float get_tx_gain_min(void) = 0; + virtual float get_tx_gain_max(void) = 0; + virtual float get_tx_gain_step(void) = 0; + + virtual void set_tx_antenna(const std::string &ant) = 0; + virtual std::string get_tx_antenna(void) = 0; + virtual std::vector get_tx_antennas(void) = 0; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_SIMPLE_DEVICE_HPP */ diff --git a/host/include/uhd/time_spec.hpp b/host/include/uhd/time_spec.hpp index e5657e555..7e182236b 100644 --- a/host/include/uhd/time_spec.hpp +++ b/host/include/uhd/time_spec.hpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include #include #ifndef INCLUDED_UHD_TIME_SPEC_HPP @@ -36,20 +37,22 @@ namespace uhd{ * Create a time_spec_t that holds a wildcard time. * This will have implementation-specific meaning. */ - time_spec_t(void){ - secs = ~0; - ticks = ~0; - } + time_spec_t(void); /*! * Create a time_spec_t from seconds and ticks. * \param new_secs the new seconds * \param new_ticks the new ticks (default = 0) */ - time_spec_t(uint32_t new_secs, uint32_t new_ticks = 0){ - secs = new_secs; - ticks = new_ticks; - } + time_spec_t(uint32_t new_secs, uint32_t new_ticks = 0); + + /*! + * Create a time_spec_t from boost posix time. + * \param time fine-grained boost posix time + * \param tick_rate the rate of ticks per second + */ + time_spec_t(boost::posix_time::ptime time, double tick_rate); + }; } //namespace uhd diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 9bbdc83c9..25a7b5abd 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -15,18 +15,14 @@ // along with this program. If not, see . // -#include -#include -#include -#include -#include -#include -#include -#include - #ifndef INCLUDED_UHD_UTILS_HPP #define INCLUDED_UHD_UTILS_HPP +#include +#include +#include +#include + /*! * Useful templated functions and classes that I like to pretend are part of stl */ @@ -40,7 +36,9 @@ namespace std{ }; #define ASSERT_THROW(_x) if (not (_x)) { \ - throw std::assert_error("Assertion Failed: " + std::string(#_x)); \ + throw std::assert_error(str(boost::format( \ + "Assertion Failed:\n %s:%d\n %s\n __/ %s __/" \ + ) % __FILE__ % __LINE__ % BOOST_CURRENT_FUNCTION % std::string(#_x))); \ } template @@ -57,9 +55,9 @@ namespace std{ return last != std::find(first, last, elem); } - template - bool has(const V &vector, const T &elem){ - return has(vector.begin(), vector.end(), elem); + template + bool has(const Iterable &iterable, const T &elem){ + return has(iterable.begin(), iterable.end(), elem); } template @@ -75,52 +73,43 @@ namespace std{ }//namespace std -/*namespace uhd{ - -inline void tune( - freq_t target_freq, - freq_t lo_offset, - wax::obj subdev_freq_proxy, - bool subdev_quadrature, - bool subdev_spectrum_inverted, - bool subdev_is_tx, - wax::obj dsp_freq_proxy, - freq_t dsp_sample_rate -){ - // Ask the d'board to tune as closely as it can to target_freq+lo_offset - subdev_freq_proxy = target_freq + lo_offset; - freq_t inter_freq = wax::cast(subdev_freq_proxy); - - // Calculate the DDC setting that will downconvert the baseband from the - // daughterboard to our target frequency. - freq_t delta_freq = target_freq - inter_freq; - freq_t delta_sign = std::signum(delta_freq); - delta_freq *= delta_sign; - delta_freq = fmod(delta_freq, dsp_sample_rate); - bool inverted = delta_freq > dsp_sample_rate/2.0; - freq_t dxc_freq = inverted? (delta_freq - dsp_sample_rate) : (-delta_freq); - dxc_freq *= delta_sign; - - // If the spectrum is inverted, and the daughterboard doesn't do - // quadrature downconversion, we can fix the inversion by flipping the - // sign of the dxc_freq... (This only happens using the basic_rx board) - if (subdev_spectrum_inverted){ - inverted = not inverted; - } - if (inverted and not subdev_quadrature){ - dxc_freq = -dxc_freq; - inverted = not inverted; - } - if (subdev_is_tx){ - dxc_freq = -dxc_freq; // down conversion versus up conversion +#include +#include +#include + +namespace uhd{ + + /*! + * Check that an element is found in a container. + * If not, throw a meaningful assertion error. + * The "what" in the error will show what is + * being set and a list of known good values. + * + * \param iterable a list of possible settings + * \param elem an element that may be in the list + * \param what a description of what is being set + * \throw assertion_error when elem not in list + */ + template void assert_has( + const Iterable &iterable, + const T &elem, + const std::string &what = "unknown" + ){ + if (std::has(iterable, elem)) return; + std::string possible_values = ""; + BOOST_FOREACH(T e, iterable){ + if (e != iterable.begin()[0]) possible_values += ", "; + possible_values += boost::lexical_cast(e); + } + throw std::assert_error(str(boost::format( + "Error: %s is not a valid %s. " + "Possible values are: [%s]." + ) + % boost::lexical_cast(elem) + % what % possible_values + )); } - dsp_freq_proxy = dxc_freq; - //freq_t actual_dxc_freq = wax::cast(dsp_freq_proxy); - - //return some kind of tune result tuple/struct -} - -} //namespace uhd*/ +}//namespace uhd #endif /* INCLUDED_UHD_UTILS_HPP */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index b1daf22d1..b141d67bb 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -23,6 +23,8 @@ SET(libuhd_sources device_addr.cpp gain_handler.cpp metadata.cpp + simple_device.cpp + time_spec.cpp wax.cpp transport/udp_simple.cpp transport/vrt.cpp diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp new file mode 100644 index 000000000..63a17c52d --- /dev/null +++ b/host/lib/simple_device.cpp @@ -0,0 +1,303 @@ +// +// 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 . +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; + +tune_result_t::tune_result_t(void){ + /* NOP */ +} + +/*********************************************************************** + * Tune Helper Function + **********************************************************************/ +static tune_result_t tune( + double target_freq, + double lo_offset, + wax::obj subdev, + wax::obj dxc, + bool is_tx +){ + wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; + bool subdev_quadrature = wax::cast(subdev[SUBDEV_PROP_QUADRATURE]); + bool subdev_spectrum_inverted = wax::cast(subdev[SUBDEV_PROP_SPECTRUM_INVERTED]); + wax::obj dxc_freq_proxy = dxc[std::string("freq")]; + double dxc_sample_rate = wax::cast(dxc[std::string("rate")]); + + // Ask the d'board to tune as closely as it can to target_freq+lo_offset + double target_inter_freq = target_freq + lo_offset; + subdev_freq_proxy = target_inter_freq; + double actual_inter_freq = wax::cast(subdev_freq_proxy); + + // Calculate the DDC setting that will downconvert the baseband from the + // daughterboard to our target frequency. + double delta_freq = target_freq - actual_inter_freq; + double delta_sign = std::signum(delta_freq); + delta_freq *= delta_sign; + delta_freq = fmod(delta_freq, dxc_sample_rate); + bool inverted = delta_freq > dxc_sample_rate/2.0; + double target_dxc_freq = inverted? (delta_freq - dxc_sample_rate) : (-delta_freq); + target_dxc_freq *= delta_sign; + + // If the spectrum is inverted, and the daughterboard doesn't do + // quadrature downconversion, we can fix the inversion by flipping the + // sign of the dxc_freq... (This only happens using the basic_rx board) + if (subdev_spectrum_inverted){ + inverted = not inverted; + } + if (inverted and not subdev_quadrature){ + target_dxc_freq *= -1.0; + inverted = not inverted; + } + // down conversion versus up conversion, fight! + // your mother is ugly and your going down... + target_dxc_freq *= (is_tx)? -1.0 : +1.0; + + dxc_freq_proxy = target_dxc_freq; + double actual_dxc_freq = wax::cast(dxc_freq_proxy); + + //return some kind of tune result tuple/struct + tune_result_t tune_result; + tune_result.target_inter_freq = target_inter_freq; + tune_result.actual_inter_freq = actual_inter_freq; + tune_result.target_dxc_freq = target_dxc_freq; + tune_result.actual_dxc_freq = actual_dxc_freq; + tune_result.spectrum_inverted = inverted; + return tune_result; +} + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +static std::string trim(const std::string &in){ + return boost::algorithm::trim_copy(in); +} + +device_addr_t args_to_device_addr(const std::string &args){ + device_addr_t addr; + + //split the args at the semi-colons + std::vector pairs; + boost::split(pairs, args, boost::is_any_of(";")); + BOOST_FOREACH(std::string pair, pairs){ + if (trim(pair) == "") continue; + + //split the key value pairs at the equals + std::vector key_val; + boost::split(key_val, pair, boost::is_any_of("=")); + if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args); + addr[trim(key_val[0])] = trim(key_val[1]); + } + + return addr; +} + +static std::vector get_xx_rates(wax::obj decerps, wax::obj rate){ + std::vector rates; + BOOST_FOREACH(size_t decerp, wax::cast >(decerps)){ + rates.push_back(wax::cast(rate)/decerp); + } + return rates; +} + +/*********************************************************************** + * Simple Device Implementation + **********************************************************************/ +class simple_device_impl : public simple_device{ +public: + simple_device_impl(const device_addr_t &addr){ + _dev = device::make(addr); + _mboard = (*_dev)[DEVICE_PROP_MBOARD]; + _rx_ddc = _mboard[named_prop_t(MBOARD_PROP_RX_DSP, "ddc0")]; + _tx_duc = _mboard[named_prop_t(MBOARD_PROP_TX_DSP, "duc0")]; + _rx_subdev = _mboard[MBOARD_PROP_RX_DBOARD][DBOARD_PROP_SUBDEV]; + _tx_subdev = _mboard[MBOARD_PROP_TX_DBOARD][DBOARD_PROP_SUBDEV]; + } + + ~simple_device_impl(void){ + /* NOP */ + } + + device::sptr get_device(void){ + return _dev; + } + + std::string get_name(void){ + return wax::cast(_mboard[MBOARD_PROP_NAME]); + } + + /******************************************************************* + * Streaming + ******************************************************************/ + void set_streaming(bool enb){ + _rx_ddc[std::string("enabled")] = enb; + } + + bool get_streaming(void){ + return wax::cast(_rx_ddc[std::string("enabled")]); + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_rate(double rate){ + double samp_rate = wax::cast(_rx_ddc[std::string("rate")]); + assert_has(get_rx_rates(), rate, "simple device rx rate"); + _rx_ddc[std::string("decim")] = size_t(samp_rate/rate); + } + + double get_rx_rate(void){ + double samp_rate = wax::cast(_rx_ddc[std::string("rate")]); + size_t decim = wax::cast(_rx_ddc[std::string("decim")]); + return samp_rate/decim; + } + + std::vector get_rx_rates(void){ + return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("rate")]); + } + + tune_result_t set_rx_freq(double target_freq, double lo_offset){ + return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); + } + + double get_rx_freq_min(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_MIN]); + } + + double get_rx_freq_max(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_MAX]); + } + + void set_rx_gain(float gain){ + _rx_subdev[SUBDEV_PROP_GAIN] = gain; + } + + float get_rx_gain(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN]); + } + + float get_rx_gain_min(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_MIN]); + } + + float get_rx_gain_max(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_MAX]); + } + + float get_rx_gain_step(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_STEP]); + } + + void set_rx_antenna(const std::string &ant){ + _rx_subdev[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_rx_antenna(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_ANTENNA]); + } + + std::vector get_rx_antennas(void){ + return wax::cast >(_rx_subdev[SUBDEV_PROP_ANTENNA_NAMES]); + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_rate(double rate){ + double samp_rate = wax::cast(_tx_duc[std::string("rate")]); + assert_has(get_tx_rates(), rate, "simple device tx rate"); + _tx_duc[std::string("interp")] = size_t(samp_rate/rate); + } + + double get_tx_rate(void){ + double samp_rate = wax::cast(_tx_duc[std::string("rate")]); + size_t interp = wax::cast(_tx_duc[std::string("interp")]); + return samp_rate/interp; + } + + std::vector get_tx_rates(void){ + return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("rate")]); + } + + tune_result_t set_tx_freq(double target_freq, double lo_offset){ + return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); + } + + double get_tx_freq_min(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_MIN]); + } + + double get_tx_freq_max(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_MAX]); + } + + void set_tx_gain(float gain){ + _tx_subdev[SUBDEV_PROP_GAIN] = gain; + } + + float get_tx_gain(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN]); + } + + float get_tx_gain_min(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_MIN]); + } + + float get_tx_gain_max(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_MAX]); + } + + float get_tx_gain_step(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_STEP]); + } + + void set_tx_antenna(const std::string &ant){ + _tx_subdev[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_tx_antenna(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_ANTENNA]); + } + + std::vector get_tx_antennas(void){ + return wax::cast >(_tx_subdev[SUBDEV_PROP_ANTENNA_NAMES]); + } + +private: + device::sptr _dev; + wax::obj _mboard; + wax::obj _rx_ddc; + wax::obj _tx_duc; + wax::obj _rx_subdev; + wax::obj _tx_subdev; +}; + +/*********************************************************************** + * The Make Function + **********************************************************************/ +simple_device::sptr simple_device::make(const std::string &args){ + return sptr(new simple_device_impl(args_to_device_addr(args))); +} diff --git a/host/lib/time_spec.cpp b/host/lib/time_spec.cpp new file mode 100644 index 000000000..193441342 --- /dev/null +++ b/host/lib/time_spec.cpp @@ -0,0 +1,40 @@ +// +// 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 . +// + +#include + +using namespace uhd; + +time_spec_t::time_spec_t(void){ + secs = ~0; + ticks = ~0; +} + +time_spec_t::time_spec_t(uint32_t new_secs, uint32_t new_ticks){ + secs = new_secs; + ticks = new_ticks; +} + +static const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); +static double time_tick_rate(boost::posix_time::time_duration::ticks_per_second()); + +time_spec_t::time_spec_t(boost::posix_time::ptime time, double tick_rate){ + boost::posix_time::time_duration td = time - epoch; + secs = td.total_seconds(); + double time_ticks_per_device_ticks = time_tick_rate/tick_rate; + ticks = td.fractional_seconds()/time_ticks_per_device_ticks; +} diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 32c64f541..da05c3241 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -16,6 +16,7 @@ // #include +#include #include "usrp2_impl.hpp" #include "dboard_interface.hpp" @@ -83,8 +84,8 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_rx_subdev_names(); return; - case DBOARD_PROP_CODEC: - throw std::runtime_error("unhandled prop in usrp2 dboard"); + //case DBOARD_PROP_CODEC: + // throw std::runtime_error("unhandled prop in usrp2 dboard"); } } @@ -113,8 +114,8 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_tx_subdev_names(); return; - case DBOARD_PROP_CODEC: - throw std::runtime_error("unhandled prop in usrp2 dboard"); + //case DBOARD_PROP_CODEC: + // throw std::runtime_error("unhandled prop in usrp2 dboard"); } } diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 7831b7667..cb7f58ec8 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -16,6 +16,7 @@ // #include +#include #include #include "usrp2_impl.hpp" @@ -110,7 +111,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ prop_names_t others = boost::assign::list_of ("rate") ("decim") - ("decim_rates") + ("decims") ("freq") ("enabled") ("stream_at") @@ -131,7 +132,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ val = _ddc_decim; return; } - else if (key_name == "decim_rates"){ + else if (key_name == "decims"){ val = _allowed_decim_and_interp_rates; return; } @@ -154,10 +155,10 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ std::string key_name = wax::cast(key); if (key_name == "decim"){ size_t new_decim = wax::cast(val); - ASSERT_THROW(std::has( + assert_has( _allowed_decim_and_interp_rates, - new_decim - )); + new_decim, "usrp2 decimation" + ); _ddc_decim = new_decim; //shadow update_ddc_config(); return; @@ -244,7 +245,7 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ prop_names_t others = boost::assign::list_of ("rate") ("interp") - ("interp_rates") + ("interps") ("freq") ; val = others; @@ -263,7 +264,7 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ val = _duc_interp; return; } - else if (key_name == "interp_rates"){ + else if (key_name == "interps"){ val = _allowed_decim_and_interp_rates; return; } @@ -282,10 +283,10 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ std::string key_name = wax::cast(key); if (key_name == "interp"){ size_t new_interp = wax::cast(val); - ASSERT_THROW(std::has( + assert_has( _allowed_decim_and_interp_rates, - new_interp - )); + new_interp, "usrp2 interpolation" + ); _duc_interp = new_interp; //shadow update_duc_config(); return; diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 8e4b2ba35..10c1ef8cf 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -91,6 +91,9 @@ typedef enum{ USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO, USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE, + USRP2_CTRL_ID_GOT_A_NEW_TIME_FOR_YOU_BRO, + USRP2_CTRL_ID_SWEET_I_GOT_THAT_TIME_DUDE, + USRP2_CTRL_ID_PEACE_OUT } usrp2_ctrl_id_t; @@ -186,6 +189,11 @@ typedef struct{ uint32_t interp; uint32_t scale_iq; } duc_args; + struct { + uint32_t secs; + uint32_t ticks; + uint8_t now; + } time_args; } data; } usrp2_ctrl_data_t; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 8e682a675..47e22c473 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -28,6 +28,10 @@ void usrp2_impl::mboard_init(void){ boost::bind(&usrp2_impl::mboard_get, this, _1, _2), boost::bind(&usrp2_impl::mboard_set, this, _1, _2) ); + + //set the time on the usrp2 as close as possible to the system utc time + boost::posix_time::ptime now(boost::posix_time::microsec_clock::universal_time()); + set_time_spec(time_spec_t(now, get_master_clock_freq()), true); } void usrp2_impl::init_clock_config(void){ @@ -64,6 +68,19 @@ void usrp2_impl::update_clock_config(void){ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THE_NEW_CLOCK_CONFIG_DUDE); } +void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_GOT_A_NEW_TIME_FOR_YOU_BRO); + out_data.data.time_args.secs = htonl(time_spec.secs); + out_data.data.time_args.ticks = htonl(time_spec.ticks); + out_data.data.time_args.now = (now)? 1 : 0; + + //send and recv + usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_SWEET_I_GOT_THAT_TIME_DUDE); +} + /*********************************************************************** * MBoard Get Properties **********************************************************************/ @@ -157,7 +174,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_PPS_SOURCE:{ std::string name = wax::cast(val); - ASSERT_THROW(_pps_source_dict.has_key(name)); + assert_has(_pps_source_dict.get_keys(), name, "usrp2 pps source"); _pps_source = name; //shadow update_clock_config(); } @@ -165,7 +182,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_PPS_POLARITY:{ std::string name = wax::cast(val); - ASSERT_THROW(_pps_polarity_dict.has_key(name)); + assert_has(_pps_polarity_dict.get_keys(), name, "usrp2 pps polarity"); _pps_polarity = name; //shadow update_clock_config(); } @@ -173,12 +190,22 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_REF_SOURCE:{ std::string name = wax::cast(val); - ASSERT_THROW(_ref_source_dict.has_key(name)); + assert_has(_ref_source_dict.get_keys(), name, "usrp2 reference source"); _ref_source = name; //shadow update_clock_config(); } return; + case MBOARD_PROP_TIME_NOW:{ + set_time_spec(wax::cast(val), true); + return; + } + + case MBOARD_PROP_TIME_NEXT_PPS:{ + set_time_spec(wax::cast(val), false); + return; + } + case MBOARD_PROP_NAME: case MBOARD_PROP_OTHERS: case MBOARD_PROP_CLOCK_RATE: @@ -192,8 +219,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_TX_DBOARD_NAMES: case MBOARD_PROP_PPS_SOURCE_NAMES: case MBOARD_PROP_REF_SOURCE_NAMES: - case MBOARD_PROP_TIME_NOW: - case MBOARD_PROP_TIME_NEXT_PPS: throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard"); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index f4e6054bd..fc713c2bf 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -135,6 +135,7 @@ private: std::string _pps_source, _pps_polarity, _ref_source; void init_clock_config(void); void update_clock_config(void); + void set_time_spec(const uhd::time_spec_t &time_spec, bool now); //mappings from clock config strings to over the wire enums uhd::dict _pps_source_dict; -- cgit v1.2.3 From 9c0fb5e15da3c8ccbc1c8537671703411b210fcf Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 10 Mar 2010 19:33:38 -0800 Subject: Filled in dboard code for basics and lf type boards. The dboard is now just a uint16 (dont bother with the enums). The dboard manager now registers subdevs with a name. The basic board code uses a static block to register itself. --- host/include/uhd/simple_device.hpp | 4 +- host/include/uhd/usrp/dboard_base.hpp | 5 +- host/include/uhd/usrp/dboard_id.hpp | 9 +- host/include/uhd/usrp/dboard_manager.hpp | 2 + host/include/uhd/utils.hpp | 5 + host/lib/CMakeLists.txt | 1 - host/lib/simple_device.cpp | 14 +- host/lib/usrp/dboard/basic.cpp | 282 +++++++++++++++++++++++++++++-- host/lib/usrp/dboard/dboards.hpp | 53 ------ host/lib/usrp/dboard_id.cpp | 34 ---- host/lib/usrp/dboard_manager.cpp | 40 ++--- 11 files changed, 307 insertions(+), 142 deletions(-) delete mode 100644 host/lib/usrp/dboard/dboards.hpp delete mode 100644 host/lib/usrp/dboard_id.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp index 64ec85a5c..69f13a8b5 100644 --- a/host/include/uhd/simple_device.hpp +++ b/host/include/uhd/simple_device.hpp @@ -70,7 +70,7 @@ public: virtual double get_rx_rate(void) = 0; virtual std::vector get_rx_rates(void) = 0; - virtual tune_result_t set_rx_freq(double target_freq, double lo_offset) = 0; + virtual tune_result_t set_rx_freq(double freq) = 0; virtual double get_rx_freq_min(void) = 0; virtual double get_rx_freq_max(void) = 0; @@ -91,7 +91,7 @@ public: virtual double get_tx_rate(void) = 0; virtual std::vector get_tx_rates(void) = 0; - virtual tune_result_t set_tx_freq(double target_freq, double lo_offset) = 0; + virtual tune_result_t set_tx_freq(double freq) = 0; virtual double get_tx_freq_min(void) = 0; virtual double get_tx_freq_max(void) = 0; diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp index b5c0d40ed..9048344ac 100644 --- a/host/include/uhd/usrp/dboard_base.hpp +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -56,9 +56,9 @@ protected: dboard_id_t get_tx_id(void); private: - std::string _subdev_name; + std::string _subdev_name; dboard_interface::sptr _dboard_interface; - dboard_id_t _rx_id, _tx_id; + dboard_id_t _rx_id, _tx_id; }; /*! @@ -71,6 +71,7 @@ public: * Create a new xcvr dboard object, override in subclasses. */ xcvr_dboard_base(ctor_args_t const&); + virtual ~xcvr_dboard_base(void); }; diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 65e3d5707..34406863d 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -16,17 +16,16 @@ // #include +#include #ifndef INCLUDED_UHD_USRP_DBOARD_ID_HPP #define INCLUDED_UHD_USRP_DBOARD_ID_HPP namespace uhd{ namespace usrp{ -enum dboard_id_t{ - ID_NONE = 0xffff, - ID_BASIC_TX = 0x0000, - ID_BASIC_RX = 0x0001 -}; +typedef uint16_t dboard_id_t; + +static const dboard_id_t ID_NONE = 0xffff; namespace dboard_id{ std::string to_string(const dboard_id_t &id); diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index 042947ac4..cf69675fc 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -44,11 +44,13 @@ public: * * \param dboard_id the dboard id (rx or tx) * \param dboard_ctor the dboard constructor function pointer + * \param name the canonical name for the dboard represented * \param subdev_names the names of the subdevs on this dboard */ static void register_subdevs( dboard_id_t dboard_id, dboard_ctor_t dboard_ctor, + const std::string &name, const prop_names_t &subdev_names ); diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 25a7b5abd..e4cfd098b 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -23,6 +23,11 @@ #include #include +/*! + * Defines a static code block that will be called before main() + */ +#define STATIC_BLOCK(_name, _code) struct _name{_name(void){_code}} _name + /*! * Useful templated functions and classes that I like to pretend are part of stl */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index b141d67bb..1d2c5471b 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -30,7 +30,6 @@ SET(libuhd_sources transport/vrt.cpp usrp/dboard/basic.cpp usrp/dboard_base.cpp - usrp/dboard_id.cpp usrp/dboard_interface.cpp usrp/dboard_manager.cpp usrp/usrp2/dboard_impl.cpp diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 63a17c52d..76f3c1262 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -179,7 +179,12 @@ public: return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("rate")]); } - tune_result_t set_rx_freq(double target_freq, double lo_offset){ + tune_result_t set_rx_freq(double target_freq){ + double lo_offset = 0.0; + //if the local oscillator will be in the passband, use an offset + if (wax::cast(_rx_subdev[SUBDEV_PROP_LO_INTERFERES])){ + lo_offset = get_rx_rate()*2.0; + } return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); } @@ -242,7 +247,12 @@ public: return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("rate")]); } - tune_result_t set_tx_freq(double target_freq, double lo_offset){ + tune_result_t set_tx_freq(double target_freq){ + double lo_offset = 0.0; + //if the local oscillator will be in the passband, use an offset + if (wax::cast(_tx_subdev[SUBDEV_PROP_LO_INTERFERES])){ + lo_offset = get_tx_rate()*2.0; + } return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); } diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index f39ebff2f..5e245a8cf 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -15,42 +15,294 @@ // along with this program. If not, see . // -#include "dboards.hpp" +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; /*********************************************************************** - * Basic RX dboard + * The basic and lf boards: + * They share a common class because only the frequency bounds differ. **********************************************************************/ -basic_rx::basic_rx(ctor_args_t const& args) : rx_dboard_base(args){ - /* NOP */ +class basic_rx : public rx_dboard_base{ +public: + basic_rx(ctor_args_t const& args, freq_t max_freq); + ~basic_rx(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + +private: + freq_t _max_freq; +}; + +class basic_tx : public tx_dboard_base{ +public: + basic_tx(ctor_args_t const& args, freq_t max_freq); + ~basic_tx(void); + + void tx_get(const wax::obj &key, wax::obj &val); + void tx_set(const wax::obj &key, const wax::obj &val); + +private: + freq_t _max_freq; +}; + +/*********************************************************************** + * Register the basic and LF dboards + **********************************************************************/ +static dboard_base::sptr make_basic_rx(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new basic_rx(args, 90e9)); +} + +static dboard_base::sptr make_basic_tx(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new basic_tx(args, 90e9)); +} + +static dboard_base::sptr make_lf_rx(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new basic_rx(args, 32e6)); +} + +static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new basic_tx(args, 32e6)); +} + +STATIC_BLOCK(reg_dboards, { + dboard_manager::register_subdevs(0x0000, &make_basic_tx, "Basic TX", list_of("")); + dboard_manager::register_subdevs(0x0001, &make_basic_rx, "Basic RX", list_of("a")("b")("ab")); + dboard_manager::register_subdevs(0x000e, &make_lf_tx, "LF TX", list_of("")); + dboard_manager::register_subdevs(0x000f, &make_lf_rx, "LF RX", list_of("a")("b")("ab")); +}); + +/*********************************************************************** + * Basic and LF RX dboard + **********************************************************************/ +basic_rx::basic_rx(ctor_args_t const& args, freq_t max_freq) : rx_dboard_base(args){ + _max_freq = max_freq; + // set the gpios to safe values (all inputs) + get_interface()->set_gpio_ddr(dboard_interface::GPIO_RX_BANK, 0x0000, 0xffff); } basic_rx::~basic_rx(void){ /* NOP */ } -void basic_rx::rx_get(const wax::obj &, wax::obj &){ - /* TODO */ +void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(wax::cast(key)){ + case SUBDEV_PROP_NAME: + val = std::string(str(boost::format("%s:%s") + % dboard_id::to_string(get_rx_id()) + % get_subdev_name() + )); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + case SUBDEV_PROP_GAIN_MAX: + case SUBDEV_PROP_GAIN_MIN: + case SUBDEV_PROP_GAIN_STEP: + val = gain_t(0); + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_FREQ: + val = freq_t(0); + return; + + case SUBDEV_PROP_FREQ_MAX: + val = +_max_freq; + return; + + case SUBDEV_PROP_FREQ_MIN: + val = -_max_freq; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); //vector of 1 empty string + return; + + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + + case SUBDEV_PROP_QUADRATURE: + val = (get_subdev_name() == "ab"); //only quadrature in ab mode + return; + + case SUBDEV_PROP_IQ_SWAPPED: + case SUBDEV_PROP_SPECTRUM_INVERTED: + case SUBDEV_PROP_LO_INTERFERES: + val = false; + return; + } } -void basic_rx::rx_set(const wax::obj &, const wax::obj &){ - /* TODO */ +void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(wax::cast(key)){ + + case SUBDEV_PROP_GAIN: + ASSERT_THROW(wax::cast(val) == gain_t(0)); + return; + + case SUBDEV_PROP_ANTENNA: + ASSERT_THROW(wax::cast(val) == std::string("")); + return; + + case SUBDEV_PROP_ENABLED: + return; // it wont do you much good, but you can set it + + case SUBDEV_PROP_NAME: + case SUBDEV_PROP_OTHERS: + case SUBDEV_PROP_GAIN_MAX: + case SUBDEV_PROP_GAIN_MIN: + case SUBDEV_PROP_GAIN_STEP: + case SUBDEV_PROP_GAIN_NAMES: + case SUBDEV_PROP_FREQ: + case SUBDEV_PROP_FREQ_MAX: + case SUBDEV_PROP_FREQ_MIN: + case SUBDEV_PROP_ANTENNA_NAMES: + case SUBDEV_PROP_QUADRATURE: + case SUBDEV_PROP_IQ_SWAPPED: + case SUBDEV_PROP_SPECTRUM_INVERTED: + case SUBDEV_PROP_LO_INTERFERES: + throw std::runtime_error(str(boost::format( + "Error: trying to set read-only property on %s subdev" + ) % dboard_id::to_string(get_rx_id()))); + } } /*********************************************************************** - * Basic TX dboard + * Basic and LF TX dboard **********************************************************************/ -basic_tx::basic_tx(ctor_args_t const& args) : tx_dboard_base(args){ - /* NOP */ +basic_tx::basic_tx(ctor_args_t const& args, freq_t max_freq) : tx_dboard_base(args){ + _max_freq = max_freq; + // set the gpios to safe values (all inputs) + get_interface()->set_gpio_ddr(dboard_interface::GPIO_TX_BANK, 0x0000, 0xffff); } basic_tx::~basic_tx(void){ /* NOP */ } -void basic_tx::tx_get(const wax::obj &, wax::obj &){ - /* TODO */ +void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(wax::cast(key)){ + case SUBDEV_PROP_NAME: + val = dboard_id::to_string(get_tx_id()); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + case SUBDEV_PROP_GAIN_MAX: + case SUBDEV_PROP_GAIN_MIN: + case SUBDEV_PROP_GAIN_STEP: + val = gain_t(0); + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_FREQ: + val = freq_t(0); + return; + + case SUBDEV_PROP_FREQ_MAX: + val = +_max_freq; + return; + + case SUBDEV_PROP_FREQ_MIN: + val = -_max_freq; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); //vector of 1 empty string + return; + + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + + case SUBDEV_PROP_QUADRATURE: + val = true; + return; + + case SUBDEV_PROP_IQ_SWAPPED: + case SUBDEV_PROP_SPECTRUM_INVERTED: + case SUBDEV_PROP_LO_INTERFERES: + val = false; + return; + } } -void basic_tx::tx_set(const wax::obj &, const wax::obj &){ - /* TODO */ +void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(wax::cast(key)){ + + case SUBDEV_PROP_GAIN: + ASSERT_THROW(wax::cast(val) == gain_t(0)); + return; + + case SUBDEV_PROP_ANTENNA: + ASSERT_THROW(wax::cast(val) == std::string("")); + return; + + case SUBDEV_PROP_ENABLED: + return; // it wont do you much good, but you can set it + + case SUBDEV_PROP_NAME: + case SUBDEV_PROP_OTHERS: + case SUBDEV_PROP_GAIN_MAX: + case SUBDEV_PROP_GAIN_MIN: + case SUBDEV_PROP_GAIN_STEP: + case SUBDEV_PROP_GAIN_NAMES: + case SUBDEV_PROP_FREQ: + case SUBDEV_PROP_FREQ_MAX: + case SUBDEV_PROP_FREQ_MIN: + case SUBDEV_PROP_ANTENNA_NAMES: + case SUBDEV_PROP_QUADRATURE: + case SUBDEV_PROP_IQ_SWAPPED: + case SUBDEV_PROP_SPECTRUM_INVERTED: + case SUBDEV_PROP_LO_INTERFERES: + throw std::runtime_error(str(boost::format( + "Error: trying to set read-only property on %s subdev" + ) % dboard_id::to_string(get_tx_id()))); + } } diff --git a/host/lib/usrp/dboard/dboards.hpp b/host/lib/usrp/dboard/dboards.hpp deleted file mode 100644 index 79b90d593..000000000 --- a/host/lib/usrp/dboard/dboards.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// 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_LOCAL_DBOARDS_HPP -#define INCLUDED_LOCAL_DBOARDS_HPP - -#include - -using namespace uhd::usrp; - -/*********************************************************************** - * The basic boards: - **********************************************************************/ -class basic_rx : public rx_dboard_base{ -public: - static dboard_base::sptr make(ctor_args_t const& args){ - return dboard_base::sptr(new basic_rx(args)); - } - basic_rx(ctor_args_t const& args); - ~basic_rx(void); - - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); -}; - -class basic_tx : public tx_dboard_base{ -public: - static dboard_base::sptr make(ctor_args_t const& args){ - return dboard_base::sptr(new basic_tx(args)); - } - basic_tx(ctor_args_t const& args); - ~basic_tx(void); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - -}; - -#endif /* INCLUDED_LOCAL_DBOARDS_HPP */ diff --git a/host/lib/usrp/dboard_id.cpp b/host/lib/usrp/dboard_id.cpp deleted file mode 100644 index d2ef7cd7d..000000000 --- a/host/lib/usrp/dboard_id.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// 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 . -// - -#include -#include -#include - -using namespace uhd::usrp; - -std::string dboard_id::to_string(const dboard_id_t &id){ - //map the dboard ids to string representations - uhd::dict id_to_str; - id_to_str[ID_NONE] = "none"; - id_to_str[ID_BASIC_TX] = "basic tx"; - id_to_str[ID_BASIC_RX] = "basic rx"; - - //get the string representation - std::string name = (id_to_str.has_key(id))? id_to_str[id] : "unknown"; - return str(boost::format("%s (0x%.4x)") % name % id); -} diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index cce239f3e..57b449175 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -18,36 +18,12 @@ #include #include #include -#include #include #include #include -#include "dboard/dboards.hpp" using namespace uhd; using namespace uhd::usrp; -using namespace boost::assign; - -/*********************************************************************** - * register internal dboards - * - * Register internal/known dboards located in this build tree. - * Each board should have entries below mapping an id to a constructor. - * The xcvr type boards should register both rx and tx sides. - * - * This function will be called before new boards are registered. - * This allows for internal boards to be externally overridden. - * This function will also be called when creating a new dboard_manager - * to ensure that the maps are filled with the entries below. - **********************************************************************/ -static void register_internal_dboards(void){ - //ensure that this function can only be called once per instance - static bool called = false; - if (called) return; called = true; - //register the known dboards (dboard id, constructor, subdev names) - dboard_manager::register_subdevs(ID_BASIC_TX, &basic_tx::make, list_of("")); - dboard_manager::register_subdevs(ID_BASIC_RX, &basic_rx::make, list_of("a")("b")("ab")); -} /*********************************************************************** * storage and registering for dboards @@ -57,15 +33,24 @@ typedef boost::tuple args_t; //map a dboard id to a dboard constructor static uhd::dict id_to_args_map; +//map a dboard id to a canonical name +static uhd::dict id_to_str; + void dboard_manager::register_subdevs( dboard_id_t dboard_id, dboard_ctor_t dboard_ctor, + const std::string &name, const prop_names_t &subdev_names ){ - register_internal_dboards(); //always call first + id_to_str[dboard_id] = name; id_to_args_map[dboard_id] = args_t(dboard_ctor, subdev_names); } +std::string dboard_id::to_string(const dboard_id_t &id){ + std::string name = (id_to_str.has_key(id))? id_to_str[id] : "unknown"; + return str(boost::format("%s (0x%.4x)") % name % id); +} + /*********************************************************************** * dboard manager implementation class **********************************************************************/ @@ -160,12 +145,12 @@ static args_t get_dboard_args( ){ //special case, its rx and the none id (0xffff) if (xx_type == "rx" and dboard_id == ID_NONE){ - return args_t(&basic_rx::make, list_of("ab")); + return get_dboard_args(0x0001, xx_type); } //special case, its tx and the none id (0xffff) if (xx_type == "tx" and dboard_id == ID_NONE){ - return args_t(&basic_tx::make, list_of("")); + return get_dboard_args(0x0000, xx_type); } //verify that there is a registered constructor for this id @@ -185,7 +170,6 @@ dboard_manager_impl::dboard_manager_impl( dboard_id_t tx_dboard_id, dboard_interface::sptr interface ){ - register_internal_dboards(); //always call first _interface = interface; dboard_ctor_t rx_dboard_ctor; prop_names_t rx_subdevs; -- cgit v1.2.3 From daed43a8a873ad5cc16ac8a3eb6db5a8fe126fa5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 11 Mar 2010 18:37:34 -0800 Subject: Cleaned up the gain handler (thing that gets and sets wildcard gains) and made use of it in the dboard manager so it intercepts the sets and gets. While doing this, fixed something with nested links in wax obj. Added some useful macros and templates to the utils. --- host/include/uhd/gain_handler.hpp | 68 +++++----- host/include/uhd/utils.hpp | 7 +- host/lib/device.cpp | 15 ++- host/lib/gain_handler.cpp | 264 ++++++++++++++++++++++---------------- host/lib/usrp/dboard/basic.cpp | 4 +- host/lib/usrp/dboard_manager.cpp | 83 +++++++----- host/lib/wax.cpp | 10 +- host/test/gain_handler_test.cpp | 18 ++- 8 files changed, 271 insertions(+), 198 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/gain_handler.hpp b/host/include/uhd/gain_handler.hpp index 06800315a..fade86f53 100644 --- a/host/include/uhd/gain_handler.hpp +++ b/host/include/uhd/gain_handler.hpp @@ -15,11 +15,9 @@ // along with this program. If not, see . // -#include #include -#include +#include #include -#include #ifndef INCLUDED_UHD_GAIN_HANDLER_HPP #define INCLUDED_UHD_GAIN_HANDLER_HPP @@ -29,29 +27,41 @@ namespace uhd{ class gain_handler{ public: typedef boost::shared_ptr sptr; + typedef boost::function is_equal_t; - template gain_handler( - wax::obj *wax_obj_ptr, const T &gain_prop, - const T &gain_min_prop, const T &gain_max_prop, - const T &gain_step_prop, const T &gain_names_prop - ){ - _wax_obj_ptr = wax_obj_ptr; - _gain_prop = gain_prop; - _gain_min_prop = gain_min_prop; - _gain_max_prop = gain_max_prop; - _gain_step_prop = gain_step_prop; - _gain_names_prop = gain_names_prop; - _is_equal = boost::bind(&gain_handler::is_equal, _1, _2); - } + /*! + * A set of properties for dealing with gains. + */ + struct gain_props_t{ + wax::obj gain_val_prop; + wax::obj gain_min_prop; + wax::obj gain_max_prop; + wax::obj gain_step_prop; + wax::obj gain_names_prop; + gain_props_t(void); //default constructor + }; - ~gain_handler(void); + /*! + * Make a new gain handler. + * The construction arguments are agnostic to the property type. + * It is up to the caller to provide an "is_equal" function that + * can tell weather two properties (in a wax obj) are equal. + * \param link a link to the wax obj with properties + * \param gain_props a struct of properties keys + * \param is_equal the function that tests for equal properties + */ + static sptr make( + const wax::obj &link, + const gain_props_t &gain_props, + is_equal_t is_equal + ); /*! * Intercept gets for overall gain, min, max, step. * Ensures that the gain name is valid. * \return true for handled, false to pass on */ - bool intercept_get(const wax::obj &key, wax::obj &val); + virtual bool intercept_get(const wax::obj &key, wax::obj &val) = 0; /*! * Intercept sets for overall gain. @@ -59,27 +69,10 @@ public: * Ensures that the new gain is within range. * \return true for handled, false to pass on */ - bool intercept_set(const wax::obj &key, const wax::obj &val); - -private: - - wax::obj *_wax_obj_ptr; - wax::obj _gain_prop; - wax::obj _gain_min_prop; - wax::obj _gain_max_prop; - wax::obj _gain_step_prop; - wax::obj _gain_names_prop; + virtual bool intercept_set(const wax::obj &key, const wax::obj &val) = 0; /*! - * Verify that the key is valid: - * If its a named prop for gain, ensure that name is valid. - * If the name if not valid, throw a std::invalid_argument. - * The name can only be valid if its in the list of gain names. - */ - void _check_key(const wax::obj &key); - - /* - * Private interface to test if two wax types are equal: + * Function template to test if two wax types are equal: * The constructor will bind an instance of this for a specific type. * This bound equals functions allows the intercept methods to be non-templated. */ @@ -91,7 +84,6 @@ private: return false; } } - boost::function _is_equal; }; diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index e4cfd098b..5d6a18b3a 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -26,7 +26,7 @@ /*! * Defines a static code block that will be called before main() */ -#define STATIC_BLOCK(_name, _code) struct _name{_name(void){_code}} _name +#define STATIC_BLOCK(_x) struct _x{_x();}_x;_x::_x() /*! * Useful templated functions and classes that I like to pretend are part of stl @@ -55,6 +55,11 @@ namespace std{ return tmp; } + template + T reduce(Iterable iterable, Function fcn, T init = 0){ + return reduce(iterable.begin(), iterable.end(), fcn, init); + } + template bool has(InputIterator first, InputIterator last, const T &elem){ return last != std::find(first, last, elem); diff --git a/host/lib/device.cpp b/host/lib/device.cpp index 82052708a..4b64e4a15 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -32,9 +32,16 @@ using namespace uhd; * Create a new device from a device address. * Based on the address, call the appropriate make functions. * \param dev_addr the device address + * \param hint the device address that was used to find the device * \return a smart pointer to a device */ -static device::sptr make_device(const device_addr_t &dev_addr){ +static device::sptr make_device(const device_addr_t &dev_addr_, const device_addr_t &hint){ + //copy keys that were in hint but not in dev_addr + //this way, we can pass additional transport arguments + device_addr_t dev_addr = dev_addr_; + BOOST_FOREACH(std::string key, hint.get_keys()){ + if (not dev_addr.has_key(key)) dev_addr[key] = hint[key]; + } //create a usrp1e if (dev_addr["type"] == "usrp1e"){ @@ -46,7 +53,9 @@ static device::sptr make_device(const device_addr_t &dev_addr){ return usrp::usrp2::make(dev_addr); } - throw std::runtime_error("cant make a device"); + throw std::runtime_error(str( + boost::format("Cant make a device for %s") % device_addr::to_string(dev_addr) + )); } /*! @@ -126,7 +135,7 @@ device::sptr device::make(const device_addr_t &hint, size_t which){ } //create and register a new device catch(const std::assert_error &e){ - device::sptr dev = make_device(dev_addr); + device::sptr dev = make_device(dev_addr, hint); hash_to_device[dev_hash] = dev; return dev; } diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index b03d5bda2..8f840ae7f 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -25,143 +26,178 @@ using namespace uhd; /*********************************************************************** - * Helper functions and macros + * helper functions **********************************************************************/ -#define GET_PROP_NAMES() \ - wax::cast((*_wax_obj_ptr)[_gain_names_prop]) - -/*! - * Helper function to simplify getting a named gain (also min, max, step). - */ -static gain_t get_named_gain(wax::obj *wax_obj_ptr, wax::obj prop, std::string name){ - return wax::cast((*wax_obj_ptr)[named_prop_t(prop, name)]); +static gain_t gain_max(gain_t a, gain_t b){ + return std::max(a, b); +} +static gain_t gain_sum(gain_t a, gain_t b){ + return std::sum(a, b); +} + +/*********************************************************************** + * gain handler implementation interface + **********************************************************************/ +class gain_handler_impl : public gain_handler{ +public: + gain_handler_impl( + const wax::obj &link, + const gain_props_t &gain_props, + is_equal_t is_equal + ); + ~gain_handler_impl(void); + bool intercept_get(const wax::obj &key, wax::obj &val); + bool intercept_set(const wax::obj &key, const wax::obj &val); + +private: + wax::obj _link; + gain_props_t _gain_props; + is_equal_t _is_equal; + + prop_names_t get_gain_names(void); + std::vector get_gains(const wax::obj &prop_key); + gain_t get_overall_gain_val(void); + gain_t get_overall_gain_min(void); + gain_t get_overall_gain_max(void); + gain_t get_overall_gain_step(void); +}; + +/*********************************************************************** + * the make function + **********************************************************************/ +gain_handler::sptr gain_handler::make( + const wax::obj &link, + const gain_props_t &gain_props, + is_equal_t is_equal +){ + return sptr(new gain_handler_impl(link, gain_props, is_equal)); } /*********************************************************************** - * Class methods of gain handler + * gain handler implementation methods **********************************************************************/ -gain_handler::~gain_handler(void){ +gain_handler::gain_props_t::gain_props_t(void){ /* NOP */ } -void gain_handler::_check_key(const wax::obj &key_){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); - - try{ - //only handle non wildcard names - ASSERT_THROW(name != ""); - - //only handle these gain props - ASSERT_THROW( - _is_equal(key, _gain_prop) or - _is_equal(key, _gain_min_prop) or - _is_equal(key, _gain_max_prop) or - _is_equal(key, _gain_step_prop) - ); - - //check that the name is allowed - prop_names_t prop_names = GET_PROP_NAMES(); - ASSERT_THROW(not std::has(prop_names.begin(), prop_names.end(), name)); - - //if we get here, throw an exception - throw std::invalid_argument(str( - boost::format("Unknown gain name %s") % name - )); - } - catch(const std::assert_error &){} +gain_handler_impl::gain_handler_impl( + const wax::obj &link, + const gain_props_t &gain_props, + is_equal_t is_equal +){ + _link = link; + _gain_props = gain_props; + _is_equal = is_equal; } -static gain_t gain_max(gain_t a, gain_t b){ - return std::max(a, b); +gain_handler_impl::~gain_handler_impl(void){ + /* NOP */ } -static gain_t gain_sum(gain_t a, gain_t b){ - return std::sum(a, b); + +prop_names_t gain_handler_impl::get_gain_names(void){ + return wax::cast(_link[_gain_props.gain_names_prop]); } -bool gain_handler::intercept_get(const wax::obj &key, wax::obj &val){ - _check_key(key); //verify the key - - std::vector gain_props = boost::assign::list_of - (_gain_prop)(_gain_min_prop)(_gain_max_prop)(_gain_step_prop); - - /*! - * Handle getting overall gains when a name is not specified. - * For the gain props below, set the overall value and return true. - */ - BOOST_FOREACH(wax::obj prop_key, gain_props){ - if (_is_equal(key, prop_key)){ - //form the gains vector from the props vector - prop_names_t prop_names = GET_PROP_NAMES(); - std::vector gains(prop_names.size()); - std::transform( - prop_names.begin(), prop_names.end(), gains.begin(), - boost::bind(get_named_gain, _wax_obj_ptr, key, _1) - ); - - //reduce across the gain vector - if (_is_equal(key, _gain_step_prop)){ - val = std::reduce(gains.begin(), gains.end(), gain_max); - } - else{ - val = std::reduce(gains.begin(), gains.end(), gain_sum); - } - return true; - } +std::vector gain_handler_impl::get_gains(const wax::obj &prop_key){ + std::vector gains; + BOOST_FOREACH(std::string name, get_gain_names()){ + gains.push_back(wax::cast(_link[named_prop_t(prop_key, name)])); } + return gains; +} + +gain_t gain_handler_impl::get_overall_gain_val(void){ + return std::reduce(get_gains(_gain_props.gain_val_prop), gain_sum); +} - return false; +gain_t gain_handler_impl::get_overall_gain_min(void){ + return std::reduce(get_gains(_gain_props.gain_min_prop), gain_sum); } -bool gain_handler::intercept_set(const wax::obj &key_, const wax::obj &val){ - _check_key(key_); //verify the key +gain_t gain_handler_impl::get_overall_gain_max(void){ + return std::reduce(get_gains(_gain_props.gain_max_prop), gain_sum); +} + +gain_t gain_handler_impl::get_overall_gain_step(void){ + return std::reduce(get_gains(_gain_props.gain_step_prop), gain_max); +} +/*********************************************************************** + * gain handler implementation get method + **********************************************************************/ +bool gain_handler_impl::intercept_get(const wax::obj &key_, wax::obj &val){ wax::obj key; std::string name; boost::tie(key, name) = extract_named_prop(key_); - /*! - * Verify that a named gain component is in range. - */ - try{ - //only handle the gain props - ASSERT_THROW(_is_equal(key, _gain_prop)); - - //check that the gain is in range - gain_t gain = wax::cast(val); - gain_t gain_min = get_named_gain(_wax_obj_ptr, _gain_min_prop, name); - gain_t gain_max = get_named_gain(_wax_obj_ptr, _gain_max_prop, name); - ASSERT_THROW(gain > gain_max or gain < gain_min); - - //if we get here, throw an exception - throw std::range_error(str( - boost::format("gain %s is out of range of (%f, %f)") % name % gain_min % gain_max - )); + //not a wildcard... dont handle (but check name) + if (name != ""){ + assert_has(get_gain_names(), name, "gain name"); + return false; + } + + if (_is_equal(key, _gain_props.gain_val_prop)){ + val = get_overall_gain_val(); + return true; + } + + if (_is_equal(key, _gain_props.gain_min_prop)){ + val = get_overall_gain_min(); + return true; } - catch(const std::assert_error &){} - - /*! - * Handle setting the overall gain. - */ - if (_is_equal(key, _gain_prop) and name == ""){ - gain_t gain = wax::cast(val); - prop_names_t prop_names = GET_PROP_NAMES(); - BOOST_FOREACH(std::string name, prop_names){ - //get the min, max, step for this gain name - gain_t gain_min = get_named_gain(_wax_obj_ptr, _gain_min_prop, name); - gain_t gain_max = get_named_gain(_wax_obj_ptr, _gain_max_prop, name); - gain_t gain_step = get_named_gain(_wax_obj_ptr, _gain_step_prop, name); - - //clip g to be within the allowed range - gain_t g = std::min(std::max(gain, gain_min), gain_max); - //set g to be a multiple of the step size - g -= fmod(g, gain_step); - //set g to be the new gain - (*_wax_obj_ptr)[named_prop_t(_gain_prop, name)] = g; - //subtract g out of the total gain left to apply - gain -= g; - } + + if (_is_equal(key, _gain_props.gain_max_prop)){ + val = get_overall_gain_max(); return true; } - return false; + if (_is_equal(key, _gain_props.gain_step_prop)){ + val = get_overall_gain_step(); + return true; + } + + return false; //not handled +} + +/*********************************************************************** + * gain handler implementation set method + **********************************************************************/ +bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //not a gain value key... dont handle + if (not _is_equal(key, _gain_props.gain_val_prop)) return false; + + gain_t gain_val = wax::cast(val); + + //not a wildcard... dont handle (but check name and range) + if (name != ""){ + assert_has(get_gain_names(), name, "gain name"); + gain_t gain_min = wax::cast(_link[named_prop_t(_gain_props.gain_min_prop, name)]); + gain_t gain_max = wax::cast(_link[named_prop_t(_gain_props.gain_max_prop, name)]); + if (gain_val > gain_max or gain_val < gain_min) throw std::range_error(str( + boost::format("A value of %f for gain %s is out of range of (%f, %f)") + % gain_val % name % gain_min % gain_max + )); + return false; + } + + //set the overall gain + BOOST_FOREACH(std::string name, get_gain_names()){ + //get the min, max, step for this gain name + gain_t gain_min = wax::cast(_link[named_prop_t(_gain_props.gain_min_prop, name)]); + gain_t gain_max = wax::cast(_link[named_prop_t(_gain_props.gain_max_prop, name)]); + gain_t gain_step = wax::cast(_link[named_prop_t(_gain_props.gain_step_prop, name)]); + + //clip g to be within the allowed range + gain_t g = std::min(std::max(gain_val, gain_min), gain_max); + //set g to be a multiple of the step size + g -= fmod(g, gain_step); + //set g to be the new gain + _link[named_prop_t(_gain_props.gain_val_prop, name)] = g; + //subtract g out of the total gain left to apply + gain_val -= g; + } + + return true; } diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 5e245a8cf..4b74e4a47 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -73,12 +73,12 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){ return dboard_base::sptr(new basic_tx(args, 32e6)); } -STATIC_BLOCK(reg_dboards, { +STATIC_BLOCK(reg_dboards){ dboard_manager::register_subdevs(0x0000, &make_basic_tx, "Basic TX", list_of("")); dboard_manager::register_subdevs(0x0001, &make_basic_rx, "Basic RX", list_of("a")("b")("ab")); dboard_manager::register_subdevs(0x000e, &make_lf_tx, "LF TX", list_of("")); dboard_manager::register_subdevs(0x000f, &make_lf_rx, "LF RX", list_of("a")("b")("ab")); -}); +} /*********************************************************************** * Basic and LF RX dboard diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 57b449175..08b92e62a 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -16,10 +16,12 @@ // #include +#include #include #include #include #include +#include #include using namespace uhd; @@ -42,6 +44,7 @@ void dboard_manager::register_subdevs( const std::string &name, const prop_names_t &subdev_names ){ + //std::cout << "registering: " << name << std::endl; id_to_str[dboard_id] = name; id_to_args_map[dboard_id] = args_t(dboard_ctor, subdev_names); } @@ -52,36 +55,7 @@ std::string dboard_id::to_string(const dboard_id_t &id){ } /*********************************************************************** - * dboard manager implementation class - **********************************************************************/ -class dboard_manager_impl : public dboard_manager{ - -public: - dboard_manager_impl( - dboard_id_t rx_dboard_id, - dboard_id_t tx_dboard_id, - dboard_interface::sptr interface - ); - ~dboard_manager_impl(void); - - //dboard_interface - prop_names_t get_rx_subdev_names(void); - prop_names_t get_tx_subdev_names(void); - wax::obj get_rx_subdev(const std::string &subdev_name); - wax::obj get_tx_subdev(const std::string &subdev_name); - -private: - //list of rx and tx dboards in this dboard_manager - //each dboard here is actually a subdevice proxy - //the subdevice proxy is internal to the cpp file - uhd::dict _rx_dboards; - uhd::dict _tx_dboards; - dboard_interface::sptr _interface; - void set_nice_gpio_pins(void); -}; - -/*********************************************************************** - * internal helper classes + * internal helper classe **********************************************************************/ /*! * A special wax proxy object that forwards calls to a subdev. @@ -95,7 +69,18 @@ public: //structors subdev_proxy(dboard_base::sptr subdev, type_t type) : _subdev(subdev), _type(type){ - /* NOP */ + //initialize gain props struct + gain_handler::gain_props_t gain_props; + gain_props.gain_val_prop = SUBDEV_PROP_GAIN; + gain_props.gain_min_prop = SUBDEV_PROP_GAIN_MIN; + gain_props.gain_max_prop = SUBDEV_PROP_GAIN_MAX; + gain_props.gain_step_prop = SUBDEV_PROP_GAIN_STEP; + gain_props.gain_names_prop = SUBDEV_PROP_GAIN_NAMES; + + //make a new gain handler + _gain_handler = gain_handler::make( + this->get_link(), gain_props, boost::bind(&gain_handler::is_equal, _1, _2) + ); } ~subdev_proxy(void){ @@ -103,11 +88,13 @@ public: } private: + gain_handler::sptr _gain_handler; dboard_base::sptr _subdev; type_t _type; //forward the get calls to the rx or tx void get(const wax::obj &key, wax::obj &val){ + if (_gain_handler->intercept_get(key, val)) return; switch(_type){ case RX_TYPE: return _subdev->rx_get(key, val); case TX_TYPE: return _subdev->tx_get(key, val); @@ -116,6 +103,7 @@ private: //forward the set calls to the rx or tx void set(const wax::obj &key, const wax::obj &val){ + if (_gain_handler->intercept_set(key, val)) return; switch(_type){ case RX_TYPE: return _subdev->rx_set(key, val); case TX_TYPE: return _subdev->tx_set(key, val); @@ -123,6 +111,35 @@ private: } }; +/*********************************************************************** + * dboard manager implementation class + **********************************************************************/ +class dboard_manager_impl : public dboard_manager{ + +public: + dboard_manager_impl( + dboard_id_t rx_dboard_id, + dboard_id_t tx_dboard_id, + dboard_interface::sptr interface + ); + ~dboard_manager_impl(void); + + //dboard_interface + prop_names_t get_rx_subdev_names(void); + prop_names_t get_tx_subdev_names(void); + wax::obj get_rx_subdev(const std::string &subdev_name); + wax::obj get_tx_subdev(const std::string &subdev_name); + +private: + //list of rx and tx dboards in this dboard_manager + //each dboard here is actually a subdevice proxy + //the subdevice proxy is internal to the cpp file + uhd::dict _rx_dboards; + uhd::dict _tx_dboards; + dboard_interface::sptr _interface; + void set_nice_gpio_pins(void); +}; + /*********************************************************************** * make routine for dboard manager **********************************************************************/ @@ -241,7 +258,7 @@ wax::obj dboard_manager_impl::get_rx_subdev(const std::string &subdev_name){ str(boost::format("Unknown rx subdev name %s") % subdev_name) ); //get a link to the rx subdev proxy - return wax::cast(_rx_dboards[subdev_name])->get_link(); + return _rx_dboards[subdev_name]->get_link(); } wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ @@ -249,7 +266,7 @@ wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ str(boost::format("Unknown tx subdev name %s") % subdev_name) ); //get a link to the tx subdev proxy - return wax::cast(_tx_dboards[subdev_name])->get_link(); + return _tx_dboards[subdev_name]->get_link(); } void dboard_manager_impl::set_nice_gpio_pins(void){ diff --git a/host/lib/wax.cpp b/host/lib/wax.cpp index c08398c50..0348d9a66 100644 --- a/host/lib/wax.cpp +++ b/host/lib/wax.cpp @@ -36,7 +36,11 @@ public: link_args_t(const wax::obj *obj_ptr) : _obj_ptr(obj_ptr){ /* NOP */ } - wax::obj & operator()(void){ + wax::obj & operator()(void) const{ + //recursively resolve link args to get at original pointer + if (_obj_ptr->type() == typeid(link_args_t)){ + return wax::cast(*_obj_ptr)(); + } return *const_cast(_obj_ptr); } private: @@ -56,10 +60,10 @@ public: proxy_args_t(const wax::obj *obj_ptr, const wax::obj &key) : _key(key){ _obj_link = obj_ptr->get_link(); } - wax::obj & operator()(void){ + wax::obj & operator()(void) const{ return wax::cast(_obj_link)(); } - const wax::obj & key(void){ + const wax::obj & key(void) const{ return _key; } private: diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index c81221aac..9a6a50dab 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -17,7 +17,9 @@ #include #include +#include #include +#include #include using namespace uhd; @@ -33,9 +35,17 @@ enum prop_t{ class gainful_obj : public wax::obj{ public: gainful_obj(void){ - _gain_handler = gain_handler::sptr(new gain_handler( - this, PROP_GAIN, PROP_GAIN_MIN, PROP_GAIN_MAX, PROP_GAIN_STEP, PROP_GAIN_NAMES - )); + //initialize gain props struct + gain_handler::gain_props_t gain_props; + gain_props.gain_val_prop = PROP_GAIN; + gain_props.gain_min_prop = PROP_GAIN_MIN; + gain_props.gain_max_prop = PROP_GAIN_MAX; + gain_props.gain_step_prop = PROP_GAIN_STEP; + gain_props.gain_names_prop = PROP_GAIN_NAMES; + //make a new gain handler + _gain_handler = gain_handler::make( + this->get_link(), gain_props, boost::bind(&gain_handler::is_equal, _1, _2) + ); _gains["g0"] = 0; _gains["g1"] = 0; _gains_min["g0"] = -10; @@ -113,7 +123,7 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ BOOST_CHECK_THROW( wax::cast(go0[named_prop_t(PROP_GAIN, "fail")]), - std::invalid_argument + std::exception ); std::cout << "verifying the overall min, max, step" << std::endl; -- cgit v1.2.3 From 2147c5f61c2eb6ef1a68419d7b1041a54cbb14a2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 12 Mar 2010 16:01:01 -0800 Subject: Removed freq min and max and gain min, max, and step... replaced it with gain and freq range tuples. This simplifies the api calls and subdev properties. --- host/include/uhd/gain_handler.hpp | 14 ++---- host/include/uhd/props.hpp | 13 +++-- host/include/uhd/simple_device.hpp | 14 ++---- host/include/uhd/utils.hpp | 5 -- host/lib/gain_handler.cpp | 98 +++++++++++++++----------------------- host/lib/simple_device.cpp | 56 +++++++++------------- host/lib/usrp/dboard/basic.cpp | 44 +++++++---------- host/lib/usrp/dboard_manager.cpp | 13 +++-- host/test/gain_handler_test.cpp | 80 +++++++++++++------------------ 9 files changed, 131 insertions(+), 206 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/gain_handler.hpp b/host/include/uhd/gain_handler.hpp index fade86f53..2d3f8a3f4 100644 --- a/host/include/uhd/gain_handler.hpp +++ b/host/include/uhd/gain_handler.hpp @@ -32,13 +32,9 @@ public: /*! * A set of properties for dealing with gains. */ - struct gain_props_t{ - wax::obj gain_val_prop; - wax::obj gain_min_prop; - wax::obj gain_max_prop; - wax::obj gain_step_prop; - wax::obj gain_names_prop; - gain_props_t(void); //default constructor + struct props_t{ + wax::obj value, range, names; + props_t(void); //default constructor }; /*! @@ -47,12 +43,12 @@ public: * It is up to the caller to provide an "is_equal" function that * can tell weather two properties (in a wax obj) are equal. * \param link a link to the wax obj with properties - * \param gain_props a struct of properties keys + * \param props a struct of properties keys * \param is_equal the function that tests for equal properties */ static sptr make( const wax::obj &link, - const gain_props_t &gain_props, + const props_t &props, is_equal_t is_equal ); diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index dea2baf52..f2ba1769f 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -30,6 +30,12 @@ namespace uhd{ typedef float gain_t; typedef double freq_t; + //gain range tuple (min, max, step) + typedef boost::tuple gain_range_t; + + //freq range tuple (min, max) + typedef boost::tuple freq_range_t; + //scalar types (have not used yet, dont uncomment until needed) //typedef int int_scalar_t; //typedef float real_scalar_t; @@ -143,13 +149,10 @@ namespace uhd{ SUBDEV_PROP_NAME, //ro, std::string SUBDEV_PROP_OTHERS, //ro, prop_names_t SUBDEV_PROP_GAIN, //rw, gain_t - SUBDEV_PROP_GAIN_MAX, //ro, gain_t - SUBDEV_PROP_GAIN_MIN, //ro, gain_t - SUBDEV_PROP_GAIN_STEP, //ro, gain_t + SUBDEV_PROP_GAIN_RANGE, //ro, gain_range_t SUBDEV_PROP_GAIN_NAMES, //ro, prop_names_t SUBDEV_PROP_FREQ, //rw, freq_t - SUBDEV_PROP_FREQ_MAX, //ro, freq_t - SUBDEV_PROP_FREQ_MIN, //ro, freq_t + SUBDEV_PROP_FREQ_RANGE, //ro, freq_range_t SUBDEV_PROP_ANTENNA, //rw, std::string SUBDEV_PROP_ANTENNA_NAMES, //ro, prop_names_t SUBDEV_PROP_ENABLED, //rw, bool diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp index 69f13a8b5..c43155ff2 100644 --- a/host/include/uhd/simple_device.hpp +++ b/host/include/uhd/simple_device.hpp @@ -71,14 +71,11 @@ public: virtual std::vector get_rx_rates(void) = 0; virtual tune_result_t set_rx_freq(double freq) = 0; - virtual double get_rx_freq_min(void) = 0; - virtual double get_rx_freq_max(void) = 0; + virtual std::vector get_rx_freq_range(void) = 0; virtual void set_rx_gain(float gain) = 0; virtual float get_rx_gain(void) = 0; - virtual float get_rx_gain_min(void) = 0; - virtual float get_rx_gain_max(void) = 0; - virtual float get_rx_gain_step(void) = 0; + virtual std::vector get_rx_gain_range(void) = 0; virtual void set_rx_antenna(const std::string &ant) = 0; virtual std::string get_rx_antenna(void) = 0; @@ -92,14 +89,11 @@ public: virtual std::vector get_tx_rates(void) = 0; virtual tune_result_t set_tx_freq(double freq) = 0; - virtual double get_tx_freq_min(void) = 0; - virtual double get_tx_freq_max(void) = 0; + virtual std::vector get_tx_freq_range(void) = 0; virtual void set_tx_gain(float gain) = 0; virtual float get_tx_gain(void) = 0; - virtual float get_tx_gain_min(void) = 0; - virtual float get_tx_gain_max(void) = 0; - virtual float get_tx_gain_step(void) = 0; + virtual std::vector get_tx_gain_range(void) = 0; virtual void set_tx_antenna(const std::string &ant) = 0; virtual std::string get_tx_antenna(void) = 0; diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 5d6a18b3a..2f6e4fd87 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -70,11 +70,6 @@ namespace std{ return has(iterable.begin(), iterable.end(), elem); } - template - T sum(const T &a, const T &b){ - return a + b; - } - template T signum(T n){ if (n < 0) return -1; if (n > 0) return 1; diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index 8f840ae7f..7eb87558c 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -25,16 +25,6 @@ using namespace uhd; -/*********************************************************************** - * helper functions - **********************************************************************/ -static gain_t gain_max(gain_t a, gain_t b){ - return std::max(a, b); -} -static gain_t gain_sum(gain_t a, gain_t b){ - return std::sum(a, b); -} - /*********************************************************************** * gain handler implementation interface **********************************************************************/ @@ -42,7 +32,7 @@ class gain_handler_impl : public gain_handler{ public: gain_handler_impl( const wax::obj &link, - const gain_props_t &gain_props, + const props_t &props, is_equal_t is_equal ); ~gain_handler_impl(void); @@ -51,15 +41,15 @@ public: private: wax::obj _link; - gain_props_t _gain_props; + props_t _props; is_equal_t _is_equal; prop_names_t get_gain_names(void); - std::vector get_gains(const wax::obj &prop_key); gain_t get_overall_gain_val(void); - gain_t get_overall_gain_min(void); - gain_t get_overall_gain_max(void); - gain_t get_overall_gain_step(void); + gain_range_t get_overall_gain_range(void); + template T get_named_prop(const wax::obj &prop, const std::string &name){ + return wax::cast(_link[named_prop_t(prop, name)]); + } }; /*********************************************************************** @@ -67,26 +57,26 @@ private: **********************************************************************/ gain_handler::sptr gain_handler::make( const wax::obj &link, - const gain_props_t &gain_props, + const props_t &props, is_equal_t is_equal ){ - return sptr(new gain_handler_impl(link, gain_props, is_equal)); + return sptr(new gain_handler_impl(link, props, is_equal)); } /*********************************************************************** * gain handler implementation methods **********************************************************************/ -gain_handler::gain_props_t::gain_props_t(void){ +gain_handler::props_t::props_t(void){ /* NOP */ } gain_handler_impl::gain_handler_impl( const wax::obj &link, - const gain_props_t &gain_props, + const props_t &props, is_equal_t is_equal ){ _link = link; - _gain_props = gain_props; + _props = props; _is_equal = is_equal; } @@ -95,31 +85,28 @@ gain_handler_impl::~gain_handler_impl(void){ } prop_names_t gain_handler_impl::get_gain_names(void){ - return wax::cast(_link[_gain_props.gain_names_prop]); + return wax::cast(_link[_props.names]); } -std::vector gain_handler_impl::get_gains(const wax::obj &prop_key){ - std::vector gains; +gain_t gain_handler_impl::get_overall_gain_val(void){ + gain_t gain_val = 0; BOOST_FOREACH(std::string name, get_gain_names()){ - gains.push_back(wax::cast(_link[named_prop_t(prop_key, name)])); + gain_val += get_named_prop(_props.value, name); } - return gains; -} - -gain_t gain_handler_impl::get_overall_gain_val(void){ - return std::reduce(get_gains(_gain_props.gain_val_prop), gain_sum); -} - -gain_t gain_handler_impl::get_overall_gain_min(void){ - return std::reduce(get_gains(_gain_props.gain_min_prop), gain_sum); -} - -gain_t gain_handler_impl::get_overall_gain_max(void){ - return std::reduce(get_gains(_gain_props.gain_max_prop), gain_sum); + return gain_val; } -gain_t gain_handler_impl::get_overall_gain_step(void){ - return std::reduce(get_gains(_gain_props.gain_step_prop), gain_max); +gain_range_t gain_handler_impl::get_overall_gain_range(void){ + gain_t gain_min = 0, gain_max = 0, gain_step = 0; + BOOST_FOREACH(std::string name, get_gain_names()){ + gain_t gain_min_tmp, gain_max_tmp, gain_step_tmp; + boost::tie(gain_min_tmp, gain_max_tmp, gain_step_tmp) = \ + get_named_prop(_props.range, name); + gain_min += gain_min_tmp; + gain_max += gain_max_tmp; + gain_step = std::max(gain_step, gain_step_tmp); + } + return gain_range_t(gain_min, gain_max, gain_step); } /*********************************************************************** @@ -135,23 +122,13 @@ bool gain_handler_impl::intercept_get(const wax::obj &key_, wax::obj &val){ return false; } - if (_is_equal(key, _gain_props.gain_val_prop)){ + if (_is_equal(key, _props.value)){ val = get_overall_gain_val(); return true; } - if (_is_equal(key, _gain_props.gain_min_prop)){ - val = get_overall_gain_min(); - return true; - } - - if (_is_equal(key, _gain_props.gain_max_prop)){ - val = get_overall_gain_max(); - return true; - } - - if (_is_equal(key, _gain_props.gain_step_prop)){ - val = get_overall_gain_step(); + if (_is_equal(key, _props.range)){ + val = get_overall_gain_range(); return true; } @@ -166,15 +143,16 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) boost::tie(key, name) = extract_named_prop(key_); //not a gain value key... dont handle - if (not _is_equal(key, _gain_props.gain_val_prop)) return false; + if (not _is_equal(key, _props.value)) return false; gain_t gain_val = wax::cast(val); //not a wildcard... dont handle (but check name and range) if (name != ""){ assert_has(get_gain_names(), name, "gain name"); - gain_t gain_min = wax::cast(_link[named_prop_t(_gain_props.gain_min_prop, name)]); - gain_t gain_max = wax::cast(_link[named_prop_t(_gain_props.gain_max_prop, name)]); + gain_t gain_min, gain_max, gain_step; + boost::tie(gain_min, gain_max, gain_step) = \ + get_named_prop(_props.range, name); if (gain_val > gain_max or gain_val < gain_min) throw std::range_error(str( boost::format("A value of %f for gain %s is out of range of (%f, %f)") % gain_val % name % gain_min % gain_max @@ -185,16 +163,16 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) //set the overall gain BOOST_FOREACH(std::string name, get_gain_names()){ //get the min, max, step for this gain name - gain_t gain_min = wax::cast(_link[named_prop_t(_gain_props.gain_min_prop, name)]); - gain_t gain_max = wax::cast(_link[named_prop_t(_gain_props.gain_max_prop, name)]); - gain_t gain_step = wax::cast(_link[named_prop_t(_gain_props.gain_step_prop, name)]); + gain_t gain_min, gain_max, gain_step; + boost::tie(gain_min, gain_max, gain_step) = \ + get_named_prop(_props.range, name); //clip g to be within the allowed range gain_t g = std::min(std::max(gain_val, gain_min), gain_max); //set g to be a multiple of the step size g -= fmod(g, gain_step); //set g to be the new gain - _link[named_prop_t(_gain_props.gain_val_prop, name)] = g; + _link[named_prop_t(_props.value, name)] = g; //subtract g out of the total gain left to apply gain_val -= g; } diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 76f3c1262..ac83ffaed 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -188,12 +188,11 @@ public: return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); } - double get_rx_freq_min(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_MIN]); - } - - double get_rx_freq_max(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_MAX]); + std::vector get_rx_freq_range(void){ + std::vector range(2); + boost::tie(range[0], range[1]) = \ + wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_RANGE]); + return range; } void set_rx_gain(float gain){ @@ -201,19 +200,14 @@ public: } float get_rx_gain(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN]); - } - - float get_rx_gain_min(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_MIN]); - } - - float get_rx_gain_max(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_MAX]); + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN]); } - float get_rx_gain_step(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_STEP]); + std::vector get_rx_gain_range(void){ + std::vector range(3); + boost::tie(range[0], range[1], range[2]) = \ + wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_RANGE]); + return range; } void set_rx_antenna(const std::string &ant){ @@ -256,12 +250,11 @@ public: return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); } - double get_tx_freq_min(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_MIN]); - } - - double get_tx_freq_max(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_MAX]); + std::vector get_tx_freq_range(void){ + std::vector range(2); + boost::tie(range[0], range[1]) = \ + wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_RANGE]); + return range; } void set_tx_gain(float gain){ @@ -269,19 +262,14 @@ public: } float get_tx_gain(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN]); - } - - float get_tx_gain_min(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_MIN]); - } - - float get_tx_gain_max(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_MAX]); + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN]); } - float get_tx_gain_step(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_STEP]); + std::vector get_tx_gain_range(void){ + std::vector range(3); + boost::tie(range[0], range[1], range[2]) = \ + wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_RANGE]); + return range; } void set_tx_antenna(const std::string &ant){ diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 4b74e4a47..1059feb19 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -111,12 +111,13 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN: - case SUBDEV_PROP_GAIN_MAX: - case SUBDEV_PROP_GAIN_MIN: - case SUBDEV_PROP_GAIN_STEP: val = gain_t(0); return; + case SUBDEV_PROP_GAIN_RANGE: + val = gain_range_t(0, 0, 0); + return; + case SUBDEV_PROP_GAIN_NAMES: val = prop_names_t(); //empty return; @@ -125,12 +126,8 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = freq_t(0); return; - case SUBDEV_PROP_FREQ_MAX: - val = +_max_freq; - return; - - case SUBDEV_PROP_FREQ_MIN: - val = -_max_freq; + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(+_max_freq, -_max_freq); return; case SUBDEV_PROP_ANTENNA: @@ -177,13 +174,10 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_NAME: case SUBDEV_PROP_OTHERS: - case SUBDEV_PROP_GAIN_MAX: - case SUBDEV_PROP_GAIN_MIN: - case SUBDEV_PROP_GAIN_STEP: + case SUBDEV_PROP_GAIN_RANGE: case SUBDEV_PROP_GAIN_NAMES: case SUBDEV_PROP_FREQ: - case SUBDEV_PROP_FREQ_MAX: - case SUBDEV_PROP_FREQ_MIN: + case SUBDEV_PROP_FREQ_RANGE: case SUBDEV_PROP_ANTENNA_NAMES: case SUBDEV_PROP_QUADRATURE: case SUBDEV_PROP_IQ_SWAPPED: @@ -223,12 +217,13 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN: - case SUBDEV_PROP_GAIN_MAX: - case SUBDEV_PROP_GAIN_MIN: - case SUBDEV_PROP_GAIN_STEP: val = gain_t(0); return; + case SUBDEV_PROP_GAIN_RANGE: + val = gain_range_t(0, 0, 0); + return; + case SUBDEV_PROP_GAIN_NAMES: val = prop_names_t(); //empty return; @@ -237,12 +232,8 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = freq_t(0); return; - case SUBDEV_PROP_FREQ_MAX: - val = +_max_freq; - return; - - case SUBDEV_PROP_FREQ_MIN: - val = -_max_freq; + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(+_max_freq, -_max_freq); return; case SUBDEV_PROP_ANTENNA: @@ -289,13 +280,10 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_NAME: case SUBDEV_PROP_OTHERS: - case SUBDEV_PROP_GAIN_MAX: - case SUBDEV_PROP_GAIN_MIN: - case SUBDEV_PROP_GAIN_STEP: + case SUBDEV_PROP_GAIN_RANGE: case SUBDEV_PROP_GAIN_NAMES: case SUBDEV_PROP_FREQ: - case SUBDEV_PROP_FREQ_MAX: - case SUBDEV_PROP_FREQ_MIN: + case SUBDEV_PROP_FREQ_RANGE: case SUBDEV_PROP_ANTENNA_NAMES: case SUBDEV_PROP_QUADRATURE: case SUBDEV_PROP_IQ_SWAPPED: diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 08b92e62a..23c2921d2 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -70,16 +70,15 @@ public: subdev_proxy(dboard_base::sptr subdev, type_t type) : _subdev(subdev), _type(type){ //initialize gain props struct - gain_handler::gain_props_t gain_props; - gain_props.gain_val_prop = SUBDEV_PROP_GAIN; - gain_props.gain_min_prop = SUBDEV_PROP_GAIN_MIN; - gain_props.gain_max_prop = SUBDEV_PROP_GAIN_MAX; - gain_props.gain_step_prop = SUBDEV_PROP_GAIN_STEP; - gain_props.gain_names_prop = SUBDEV_PROP_GAIN_NAMES; + gain_handler::props_t gain_props; + gain_props.value = SUBDEV_PROP_GAIN; + gain_props.range = SUBDEV_PROP_GAIN_RANGE; + gain_props.names = SUBDEV_PROP_GAIN_NAMES; //make a new gain handler _gain_handler = gain_handler::make( - this->get_link(), gain_props, boost::bind(&gain_handler::is_equal, _1, _2) + this->get_link(), gain_props, + boost::bind(&gain_handler::is_equal, _1, _2) ); } diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index 9a6a50dab..51497b741 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -25,10 +25,8 @@ using namespace uhd; enum prop_t{ - PROP_GAIN, - PROP_GAIN_MIN, - PROP_GAIN_MAX, - PROP_GAIN_STEP, + PROP_GAIN_VALUE, + PROP_GAIN_RANGE, PROP_GAIN_NAMES }; @@ -36,24 +34,19 @@ class gainful_obj : public wax::obj{ public: gainful_obj(void){ //initialize gain props struct - gain_handler::gain_props_t gain_props; - gain_props.gain_val_prop = PROP_GAIN; - gain_props.gain_min_prop = PROP_GAIN_MIN; - gain_props.gain_max_prop = PROP_GAIN_MAX; - gain_props.gain_step_prop = PROP_GAIN_STEP; - gain_props.gain_names_prop = PROP_GAIN_NAMES; + gain_handler::props_t gain_props; + gain_props.value = PROP_GAIN_VALUE; + gain_props.range = PROP_GAIN_RANGE; + gain_props.names = PROP_GAIN_NAMES; //make a new gain handler _gain_handler = gain_handler::make( - this->get_link(), gain_props, boost::bind(&gain_handler::is_equal, _1, _2) + this->get_link(), gain_props, + boost::bind(&gain_handler::is_equal, _1, _2) ); - _gains["g0"] = 0; - _gains["g1"] = 0; - _gains_min["g0"] = -10; - _gains_min["g1"] = 0; - _gains_max["g0"] = 0; - _gains_max["g1"] = 100; - _gains_step["g0"] = .1; - _gains_step["g1"] = 1.5; + _gain_values["g0"] = 0; + _gain_values["g1"] = 0; + _gain_ranges["g0"] = gain_range_t(-10, 0, .1); + _gain_ranges["g1"] = gain_range_t(0, 100, 1.5); } ~gainful_obj(void){} @@ -67,24 +60,16 @@ private: //handle the get request conditioned on the key switch(wax::cast(key)){ - case PROP_GAIN: - val = _gains[name]; + case PROP_GAIN_VALUE: + val = _gain_values[name]; return; - case PROP_GAIN_MIN: - val = _gains_min[name]; - return; - - case PROP_GAIN_MAX: - val = _gains_max[name]; - return; - - case PROP_GAIN_STEP: - val = _gains_step[name]; + case PROP_GAIN_RANGE: + val = _gain_ranges[name]; return; case PROP_GAIN_NAMES: - val = prop_names_t(_gains.get_keys()); + val = _gain_values.get_keys(); return; } } @@ -97,23 +82,19 @@ private: //handle the get request conditioned on the key switch(wax::cast(key)){ - case PROP_GAIN: - _gains[name] = wax::cast(val); + case PROP_GAIN_VALUE: + _gain_values[name] = wax::cast(val); return; - case PROP_GAIN_MIN: - case PROP_GAIN_MAX: - case PROP_GAIN_STEP: + case PROP_GAIN_RANGE: case PROP_GAIN_NAMES: throw std::runtime_error("cannot set this property"); } } gain_handler::sptr _gain_handler; - uhd::dict _gains; - uhd::dict _gains_min; - uhd::dict _gains_max; - uhd::dict _gains_step; + uhd::dict _gain_values; + uhd::dict _gain_ranges; }; @@ -122,17 +103,20 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ gainful_obj go0; BOOST_CHECK_THROW( - wax::cast(go0[named_prop_t(PROP_GAIN, "fail")]), + wax::cast(go0[named_prop_t(PROP_GAIN_VALUE, "fail")]), std::exception ); std::cout << "verifying the overall min, max, step" << std::endl; - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_MIN]), gain_t(-10)); - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_MAX]), gain_t(100)); - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_STEP]), gain_t(1.5)); + gain_t gain_min, gain_max, gain_step; + boost::tie(gain_min, gain_max, gain_step) = \ + wax::cast(go0[PROP_GAIN_RANGE]); + BOOST_CHECK_EQUAL(gain_min, gain_t(-10)); + BOOST_CHECK_EQUAL(gain_max, gain_t(100)); + BOOST_CHECK_EQUAL(gain_step, gain_t(1.5)); std::cout << "verifying the overall gain" << std::endl; - go0[named_prop_t(PROP_GAIN, "g0")] = gain_t(-5); - go0[named_prop_t(PROP_GAIN, "g1")] = gain_t(30); - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN]), gain_t(25)); + go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = gain_t(-5); + go0[named_prop_t(PROP_GAIN_VALUE, "g1")] = gain_t(30); + BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_VALUE]), gain_t(25)); } -- cgit v1.2.3 From 1ba6aafa678cdf61aef44de1d22ec72653e87ec7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 12 Mar 2010 18:04:31 -0800 Subject: handle getting and setting mac and ip addr from the host --- host/lib/usrp/usrp2/mboard_impl.cpp | 69 +++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 47e22c473..b66de8262 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -16,6 +16,7 @@ // #include +#include #include "usrp2_impl.hpp" using namespace uhd; @@ -88,14 +89,50 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ wax::obj key; std::string name; boost::tie(key, name) = extract_named_prop(key_); + //handle the other props + if (key.type() == typeid(std::string)){ + if (wax::cast(key) == "mac-addr"){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO); + + //send and recv + usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); + + //extract the address + val = reinterpret_cast(in_data.data.mac_addr)->to_string(); + return; + } + + if (wax::cast(key) == "ip-addr"){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); + + //send and recv + usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); + + //extract the address + val = boost::asio::ip::address_v4(ntohl(in_data.data.ip_addr)).to_string(); + return; + } + } + //handle the get request conditioned on the key switch(wax::cast(key)){ case MBOARD_PROP_NAME: val = std::string("usrp2 mboard"); return; - case MBOARD_PROP_OTHERS: - val = prop_names_t(); //empty other props + case MBOARD_PROP_OTHERS:{ + prop_names_t others = boost::assign::list_of + ("mac-addr") + ("ip-addr") + ; + val = others; + } return; case MBOARD_PROP_RX_DBOARD: @@ -169,6 +206,34 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ * MBoard Set Properties **********************************************************************/ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ + //handle the other props + if (key.type() == typeid(std::string)){ + if (wax::cast(key) == "mac-addr"){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO); + mac_addr_t mac_addr(wax::cast(val)); + std::memcpy(out_data.data.mac_addr, &mac_addr, sizeof(mac_addr_t)); + + //send and recv + usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); + return; + } + + if (wax::cast(key) == "ip-addr"){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO); + out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(wax::cast(val)).to_ulong()); + + //send and recv + usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); + return; + } + } + //handle the get request conditioned on the key switch(wax::cast(key)){ -- cgit v1.2.3 From 7590f187d0414fd05e23828488166bc4bc88df26 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 15 Mar 2010 12:15:33 -0700 Subject: Device sub classes can register themselves. Simplifies device.cpp internals. Added static instance macro for lazy instantiation of static variables. --- host/include/uhd/device.hpp | 13 +++++ host/include/uhd/dict.hpp | 8 +++ host/include/uhd/usrp/dboard_manager.hpp | 4 +- host/include/uhd/utils.hpp | 13 ++++- host/lib/device.cpp | 92 ++++++++++++++++---------------- host/lib/usrp/dboard/basic.cpp | 8 +-- host/lib/usrp/dboard_manager.cpp | 53 +++++++++--------- host/lib/usrp/usrp2/usrp2_impl.cpp | 5 +- 8 files changed, 117 insertions(+), 79 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 47dfa4328..c9d608bcf 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -37,6 +37,19 @@ class device : boost::noncopyable, public wax::obj{ public: typedef boost::shared_ptr sptr; + typedef boost::function discover_t; + typedef boost::function make_t; + + /*! + * Register a device into the discovery and factory system. + * + * \param discover a function that discovers devices + * \param make a factory function that makes a device + */ + static void register_device( + const discover_t &discover, + const make_t &make + ); /*! * \brief Discover usrp devices attached to the host. diff --git a/host/include/uhd/dict.hpp b/host/include/uhd/dict.hpp index 1ed28551a..2224a0063 100644 --- a/host/include/uhd/dict.hpp +++ b/host/include/uhd/dict.hpp @@ -56,6 +56,14 @@ namespace uhd{ /* NOP */ } + /*! + * Get the number of elements in this dict. + * \param the number of elements + */ + std::size_t size(void) const{ + return _map.size(); + } + /*! * Get a list of the keys in this dict. * \return vector of keys diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index cf69675fc..0c32c6dba 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -40,14 +40,14 @@ public: typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t const&); /*! - * Register subdevices for a given dboard id. + * Register a dboard into the system. * * \param dboard_id the dboard id (rx or tx) * \param dboard_ctor the dboard constructor function pointer * \param name the canonical name for the dboard represented * \param subdev_names the names of the subdevs on this dboard */ - static void register_subdevs( + static void register_dboard( dboard_id_t dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 2f6e4fd87..995cb9926 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -23,10 +23,19 @@ #include #include +/*! + * Defines a function that implements the "construct on first use" idiom + * \param _t the type definition for the instance + * \param _x the name of the defined function + * \return a reference to the lazy instance + */ +#define STATIC_INSTANCE(_t, _x) static _t &_x(){static _t _x; return _x;} + /*! * Defines a static code block that will be called before main() + * \param _x the name of the defined struct (must be unique in file) */ -#define STATIC_BLOCK(_x) struct _x{_x();}_x;_x::_x() +#define STATIC_BLOCK(_x) static struct _x{_x();}_x;_x::_x() /*! * Useful templated functions and classes that I like to pretend are part of stl @@ -42,7 +51,7 @@ namespace std{ #define ASSERT_THROW(_x) if (not (_x)) { \ throw std::assert_error(str(boost::format( \ - "Assertion Failed:\n %s:%d\n %s\n __/ %s __/" \ + "Assertion Failed:\n %s:%d\n %s\n ---> %s <---" \ ) % __FILE__ % __LINE__ % BOOST_CURRENT_FUNCTION % std::string(#_x))); \ } diff --git a/host/lib/device.cpp b/host/lib/device.cpp index 4b64e4a15..a87ba83eb 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -15,49 +15,22 @@ // asize_t with this program. If not, see . // -#include -#include +#include #include #include #include #include #include #include +#include #include #include using namespace uhd; -/*! - * Create a new device from a device address. - * Based on the address, call the appropriate make functions. - * \param dev_addr the device address - * \param hint the device address that was used to find the device - * \return a smart pointer to a device - */ -static device::sptr make_device(const device_addr_t &dev_addr_, const device_addr_t &hint){ - //copy keys that were in hint but not in dev_addr - //this way, we can pass additional transport arguments - device_addr_t dev_addr = dev_addr_; - BOOST_FOREACH(std::string key, hint.get_keys()){ - if (not dev_addr.has_key(key)) dev_addr[key] = hint[key]; - } - - //create a usrp1e - if (dev_addr["type"] == "usrp1e"){ - return usrp::usrp1e::make(dev_addr); - } - - //create a usrp2 - if (dev_addr["type"] == "usrp2"){ - return usrp::usrp2::make(dev_addr); - } - - throw std::runtime_error(str( - boost::format("Cant make a device for %s") % device_addr::to_string(dev_addr) - )); -} - +/*********************************************************************** + * Helper Functions + **********************************************************************/ /*! * Make a device hash that maps 1 to 1 with a device address. * The hash will be used to identify created devices. @@ -80,20 +53,35 @@ static size_t hash_device_addr( return hash; } +/*********************************************************************** + * Registration + **********************************************************************/ +typedef boost::tuple dev_fcn_reg_t; + +// instantiate the device function registry container +STATIC_INSTANCE(std::vector, get_dev_fcn_regs) + +void device::register_device( + const discover_t &discover, + const make_t &make +){ + //std::cout << "registering device" << std::endl; + get_dev_fcn_regs().push_back(dev_fcn_reg_t(discover, make)); +} + /*********************************************************************** * Discover **********************************************************************/ device_addrs_t device::discover(const device_addr_t &hint){ device_addrs_t device_addrs; - //discover the usrp1es - std::vector usrp2_addrs = usrp::usrp1e::discover(hint); - device_addrs.insert(device_addrs.begin(), usrp2_addrs.begin(), usrp2_addrs.end()); - - //discover the usrp2s - if (hint.has_key("addr")){ - std::vector usrp2_addrs = usrp::usrp2::discover(hint); - device_addrs.insert(device_addrs.begin(), usrp2_addrs.begin(), usrp2_addrs.end()); + BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){ + device_addrs_t discovered_addrs = fcn.get<0>()(hint); + device_addrs.insert( + device_addrs.begin(), + discovered_addrs.begin(), + discovered_addrs.end() + ); } return device_addrs; @@ -103,24 +91,38 @@ device_addrs_t device::discover(const device_addr_t &hint){ * Make **********************************************************************/ device::sptr device::make(const device_addr_t &hint, size_t which){ - std::vector device_addrs = discover(hint); + typedef boost::tuple dev_addr_make_t; + std::vector dev_addr_makers; + + BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){ + BOOST_FOREACH(device_addr_t dev_addr, fcn.get<0>()(hint)){ + //copy keys that were in hint but not in dev_addr + //this way, we can pass additional transport arguments + BOOST_FOREACH(std::string key, hint.get_keys()){ + if (not dev_addr.has_key(key)) dev_addr[key] = hint[key]; + } + //append the discovered address and its factory function + dev_addr_makers.push_back(dev_addr_make_t(dev_addr, fcn.get<1>())); + } + } //check that we found any devices - if (device_addrs.size() == 0){ + if (dev_addr_makers.size() == 0){ throw std::runtime_error(str( boost::format("No devices found for %s") % device_addr::to_string(hint) )); } //check that the which index is valid - if (device_addrs.size() <= which){ + if (dev_addr_makers.size() <= which){ throw std::runtime_error(str( boost::format("No device at index %d for %s") % which % device_addr::to_string(hint) )); } //create a unique hash for the device address - device_addr_t dev_addr = device_addrs.at(which); + device_addr_t dev_addr; make_t maker; + boost::tie(dev_addr, maker) = dev_addr_makers.at(which); size_t dev_hash = hash_device_addr(dev_addr); //std::cout << boost::format("Hash: %u") % dev_hash << std::endl; @@ -135,7 +137,7 @@ device::sptr device::make(const device_addr_t &hint, size_t which){ } //create and register a new device catch(const std::assert_error &e){ - device::sptr dev = make_device(dev_addr, hint); + device::sptr dev = maker(dev_addr); hash_to_device[dev_hash] = dev; return dev; } diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 1059feb19..e719950e8 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -74,10 +74,10 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){ } STATIC_BLOCK(reg_dboards){ - dboard_manager::register_subdevs(0x0000, &make_basic_tx, "Basic TX", list_of("")); - dboard_manager::register_subdevs(0x0001, &make_basic_rx, "Basic RX", list_of("a")("b")("ab")); - dboard_manager::register_subdevs(0x000e, &make_lf_tx, "LF TX", list_of("")); - dboard_manager::register_subdevs(0x000f, &make_lf_rx, "LF RX", list_of("a")("b")("ab")); + dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX", list_of("")); + dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("a")("b")("ab")); + dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX", list_of("")); + dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("a")("b")("ab")); } /*********************************************************************** diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 23c2921d2..eeabbda99 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -30,27 +30,30 @@ using namespace uhd::usrp; /*********************************************************************** * storage and registering for dboards **********************************************************************/ -typedef boost::tuple args_t; +//dboard registry tuple: dboard constructor, canonical name, subdev names +typedef boost::tuple args_t; //map a dboard id to a dboard constructor -static uhd::dict id_to_args_map; +typedef uhd::dict id_to_args_map_t; +STATIC_INSTANCE(id_to_args_map_t, get_id_to_args_map) -//map a dboard id to a canonical name -static uhd::dict id_to_str; - -void dboard_manager::register_subdevs( +void dboard_manager::register_dboard( dboard_id_t dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, const prop_names_t &subdev_names ){ //std::cout << "registering: " << name << std::endl; - id_to_str[dboard_id] = name; - id_to_args_map[dboard_id] = args_t(dboard_ctor, subdev_names); + if (get_id_to_args_map().has_key(dboard_id)){ + throw std::runtime_error(str(boost::format( + "The dboard id 0x%.4x is already registered to %s." + ) % dboard_id % dboard_id::to_string(dboard_id))); + } + get_id_to_args_map()[dboard_id] = args_t(dboard_ctor, name, subdev_names); } std::string dboard_id::to_string(const dboard_id_t &id){ - std::string name = (id_to_str.has_key(id))? id_to_str[id] : "unknown"; + std::string name = (get_id_to_args_map().has_key(id))? get_id_to_args_map()[id].get<1>() : "unknown"; return str(boost::format("%s (0x%.4x)") % name % id); } @@ -170,7 +173,7 @@ static args_t get_dboard_args( } //verify that there is a registered constructor for this id - if (not id_to_args_map.has_key(dboard_id)){ + if (not get_id_to_args_map().has_key(dboard_id)){ throw std::runtime_error(str( boost::format("Unregistered %s dboard id: %s") % xx_type % dboard_id::to_string(dboard_id) @@ -178,7 +181,7 @@ static args_t get_dboard_args( } //return the dboard args for this id - return id_to_args_map[dboard_id]; + return get_id_to_args_map()[dboard_id]; } dboard_manager_impl::dboard_manager_impl( @@ -188,11 +191,11 @@ dboard_manager_impl::dboard_manager_impl( ){ _interface = interface; - dboard_ctor_t rx_dboard_ctor; prop_names_t rx_subdevs; - boost::tie(rx_dboard_ctor, rx_subdevs) = get_dboard_args(rx_dboard_id, "rx"); + dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; + boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(rx_dboard_id, "rx"); - dboard_ctor_t tx_dboard_ctor; prop_names_t tx_subdevs; - boost::tie(tx_dboard_ctor, tx_subdevs) = get_dboard_args(tx_dboard_id, "tx"); + dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs; + boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(tx_dboard_id, "tx"); //initialize the gpio pins before creating subdevs set_nice_gpio_pins(); @@ -200,16 +203,16 @@ dboard_manager_impl::dboard_manager_impl( //make xcvr subdevs (make one subdev for both rx and tx dboards) if (rx_dboard_ctor == tx_dboard_ctor){ ASSERT_THROW(rx_subdevs == tx_subdevs); - BOOST_FOREACH(std::string name, rx_subdevs){ + BOOST_FOREACH(std::string subdev, rx_subdevs){ dboard_base::sptr xcvr_dboard = rx_dboard_ctor( - dboard_base::ctor_args_t(name, interface, rx_dboard_id, tx_dboard_id) + dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, tx_dboard_id) ); //create a rx proxy for this xcvr board - _rx_dboards[name] = subdev_proxy::sptr( + _rx_dboards[subdev] = subdev_proxy::sptr( new subdev_proxy(xcvr_dboard, subdev_proxy::RX_TYPE) ); //create a tx proxy for this xcvr board - _tx_dboards[name] = subdev_proxy::sptr( + _tx_dboards[subdev] = subdev_proxy::sptr( new subdev_proxy(xcvr_dboard, subdev_proxy::TX_TYPE) ); } @@ -218,22 +221,22 @@ dboard_manager_impl::dboard_manager_impl( //make tx and rx subdevs (separate subdevs for rx and tx dboards) else{ //make the rx subdevs - BOOST_FOREACH(std::string name, rx_subdevs){ + BOOST_FOREACH(std::string subdev, rx_subdevs){ dboard_base::sptr rx_dboard = rx_dboard_ctor( - dboard_base::ctor_args_t(name, interface, rx_dboard_id, ID_NONE) + dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, ID_NONE) ); //create a rx proxy for this rx board - _rx_dboards[name] = subdev_proxy::sptr( + _rx_dboards[subdev] = subdev_proxy::sptr( new subdev_proxy(rx_dboard, subdev_proxy::RX_TYPE) ); } //make the tx subdevs - BOOST_FOREACH(std::string name, tx_subdevs){ + BOOST_FOREACH(std::string subdev, tx_subdevs){ dboard_base::sptr tx_dboard = tx_dboard_ctor( - dboard_base::ctor_args_t(name, interface, ID_NONE, tx_dboard_id) + dboard_base::ctor_args_t(subdev, interface, ID_NONE, tx_dboard_id) ); //create a tx proxy for this tx board - _tx_dboards[name] = subdev_proxy::sptr( + _tx_dboards[subdev] = subdev_proxy::sptr( new subdev_proxy(tx_dboard, subdev_proxy::TX_TYPE) ); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 58c82303f..850a738d4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -26,6 +26,10 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; +STATIC_BLOCK(register_device){ + device::register_device(&usrp2::discover, &usrp2::make); +} + /*********************************************************************** * Discovery over the udp transport **********************************************************************/ @@ -57,7 +61,6 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr)); device_addr_t new_addr; new_addr["name"] = "USRP2"; - new_addr["type"] = "usrp2"; new_addr["transport"] = "udp"; new_addr["addr"] = ip_addr.to_string(); usrp2_addrs.push_back(new_addr); -- cgit v1.2.3 From fc40ff2f1327d01c72c4d7dbc07a14e473251981 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 15 Mar 2010 17:43:10 -0700 Subject: Replaced uses of wax:cast with the templated as method (like in boost program options). --- host/include/uhd/gain_handler.hpp | 2 +- host/include/uhd/props.hpp | 2 +- host/include/uhd/wax.hpp | 43 ++++++++++------------------- host/lib/gain_handler.cpp | 6 ++--- host/lib/simple_device.cpp | 54 ++++++++++++++++++------------------- host/lib/usrp/dboard/basic.cpp | 16 +++++------ host/lib/usrp/usrp2/dboard_impl.cpp | 4 +-- host/lib/usrp/usrp2/dsp_impl.cpp | 24 ++++++++--------- host/lib/usrp/usrp2/mboard_impl.cpp | 26 +++++++++--------- host/lib/usrp/usrp2/usrp2_impl.cpp | 2 +- host/lib/wax.cpp | 6 ++--- host/test/gain_handler_test.cpp | 12 ++++----- host/test/wax_test.cpp | 15 ++++++----- 13 files changed, 99 insertions(+), 113 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/gain_handler.hpp b/host/include/uhd/gain_handler.hpp index 2d3f8a3f4..a71d63c84 100644 --- a/host/include/uhd/gain_handler.hpp +++ b/host/include/uhd/gain_handler.hpp @@ -74,7 +74,7 @@ public: */ template static bool is_equal(const wax::obj &a, const wax::obj &b){ try{ - return wax::cast(a) == wax::cast(b); + return a.as() == b.as(); } catch(const wax::bad_cast &){ return false; diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index f2ba1769f..0dddba647 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -57,7 +57,7 @@ namespace uhd{ */ inline named_prop_t extract_named_prop(const wax::obj &key, const std::string &name = ""){ if (key.type() == typeid(named_prop_t)){ - return wax::cast(key); + return key.as(); } return named_prop_t(key, name); } diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp index 4fd54ba14..0291a06b7 100644 --- a/host/include/uhd/wax.hpp +++ b/host/include/uhd/wax.hpp @@ -19,31 +19,34 @@ #define INCLUDED_WAX_HPP #include -#include /*! * WAX - it's a metaphor! * - * The WAX framework allows object to have generic/anyobj properties. + * The WAX framework allows an object to have generic/anyobj properties. * These properties can be addressed through generic/anyobj identifiers. - * A property of a WAX object may even be another WAX object. * - * When a property is a WAX object, the returned value must be an obj pointer. - * A WAX object provides two objs of pointers: obj::ptr and obj::sptr. - * The choice of pointer vs smart pointer depends on the owner of the memory. + * The WAX object itself is an anytype container much like boost::any. + * To retrieve the value of the appropriate type, use my_obj.as(). * * Proprties may be referenced though the [] overloaded operator. * The [] operator returns a special proxy that allows for assigment. * Also, the [] operators may be chained as in the folowing examples: - * my_obj[prop1][prop2][prop3] = value - * value = my_obj[prop1][prop2][prop3] + * my_obj[prop1][prop2][prop3] = value; + * value = my_obj[prop1][prop2][prop3].as(); * - * Any value returned from an access operation is of wax::obj. - * To use this value, it must be cast with wax::cast(value). + * Property nesting occurs when a WAX object gets another object's link. + * This special link is obtained through a call to my_obj.get_link(). */ namespace wax{ + /*! + * The wax::bad cast will be thrown when + * cast is called with the wrong typeid. + */ + typedef boost::bad_any_cast bad_cast; + /*! * WAX object base class: * @@ -126,7 +129,7 @@ namespace wax{ /*! * Cast this obj into the desired type. - * Usage myobj.as() + * Usage: myobj.as() * * \return an object of the desired type * \throw wax::bad_cast when the cast fails @@ -154,24 +157,6 @@ namespace wax{ }; - /*! - * The wax::bad cast will be thrown when - * cast is called with the wrong typeid. - */ - typedef boost::bad_any_cast bad_cast; - - /*! - * Cast a wax::obj into the desired obj. - * Usage wax::cast(my_value). - * - * \param val the obj to cast - * \return an object of the desired type - * \throw wax::bad_cast when the cast fails - */ - template T cast(const obj &val){ - return val.as(); - } - } //namespace wax #endif /* INCLUDED_WAX_HPP */ diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index 7eb87558c..847bc0528 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -48,7 +48,7 @@ private: gain_t get_overall_gain_val(void); gain_range_t get_overall_gain_range(void); template T get_named_prop(const wax::obj &prop, const std::string &name){ - return wax::cast(_link[named_prop_t(prop, name)]); + return _link[named_prop_t(prop, name)].as(); } }; @@ -85,7 +85,7 @@ gain_handler_impl::~gain_handler_impl(void){ } prop_names_t gain_handler_impl::get_gain_names(void){ - return wax::cast(_link[_props.names]); + return _link[_props.names].as(); } gain_t gain_handler_impl::get_overall_gain_val(void){ @@ -145,7 +145,7 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) //not a gain value key... dont handle if (not _is_equal(key, _props.value)) return false; - gain_t gain_val = wax::cast(val); + gain_t gain_val = val.as(); //not a wildcard... dont handle (but check name and range) if (name != ""){ diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index ac83ffaed..62a38cb79 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -42,15 +42,15 @@ static tune_result_t tune( bool is_tx ){ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; - bool subdev_quadrature = wax::cast(subdev[SUBDEV_PROP_QUADRATURE]); - bool subdev_spectrum_inverted = wax::cast(subdev[SUBDEV_PROP_SPECTRUM_INVERTED]); + bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as(); + bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as(); wax::obj dxc_freq_proxy = dxc[std::string("freq")]; - double dxc_sample_rate = wax::cast(dxc[std::string("rate")]); + double dxc_sample_rate = dxc[std::string("rate")].as(); // Ask the d'board to tune as closely as it can to target_freq+lo_offset double target_inter_freq = target_freq + lo_offset; subdev_freq_proxy = target_inter_freq; - double actual_inter_freq = wax::cast(subdev_freq_proxy); + double actual_inter_freq = subdev_freq_proxy.as(); // Calculate the DDC setting that will downconvert the baseband from the // daughterboard to our target frequency. @@ -77,7 +77,7 @@ static tune_result_t tune( target_dxc_freq *= (is_tx)? -1.0 : +1.0; dxc_freq_proxy = target_dxc_freq; - double actual_dxc_freq = wax::cast(dxc_freq_proxy); + double actual_dxc_freq = dxc_freq_proxy.as(); //return some kind of tune result tuple/struct tune_result_t tune_result; @@ -117,8 +117,8 @@ device_addr_t args_to_device_addr(const std::string &args){ static std::vector get_xx_rates(wax::obj decerps, wax::obj rate){ std::vector rates; - BOOST_FOREACH(size_t decerp, wax::cast >(decerps)){ - rates.push_back(wax::cast(rate)/decerp); + BOOST_FOREACH(size_t decerp, decerps.as >()){ + rates.push_back(rate.as()/decerp); } return rates; } @@ -146,7 +146,7 @@ public: } std::string get_name(void){ - return wax::cast(_mboard[MBOARD_PROP_NAME]); + return _mboard[MBOARD_PROP_NAME].as(); } /******************************************************************* @@ -157,21 +157,21 @@ public: } bool get_streaming(void){ - return wax::cast(_rx_ddc[std::string("enabled")]); + return _rx_ddc[std::string("enabled")].as(); } /******************************************************************* * RX methods ******************************************************************/ void set_rx_rate(double rate){ - double samp_rate = wax::cast(_rx_ddc[std::string("rate")]); + double samp_rate = _rx_ddc[std::string("rate")].as(); assert_has(get_rx_rates(), rate, "simple device rx rate"); _rx_ddc[std::string("decim")] = size_t(samp_rate/rate); } double get_rx_rate(void){ - double samp_rate = wax::cast(_rx_ddc[std::string("rate")]); - size_t decim = wax::cast(_rx_ddc[std::string("decim")]); + double samp_rate = _rx_ddc[std::string("rate")].as(); + size_t decim = _rx_ddc[std::string("decim")].as(); return samp_rate/decim; } @@ -182,7 +182,7 @@ public: tune_result_t set_rx_freq(double target_freq){ double lo_offset = 0.0; //if the local oscillator will be in the passband, use an offset - if (wax::cast(_rx_subdev[SUBDEV_PROP_LO_INTERFERES])){ + if (_rx_subdev[SUBDEV_PROP_LO_INTERFERES].as()){ lo_offset = get_rx_rate()*2.0; } return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); @@ -191,7 +191,7 @@ public: std::vector get_rx_freq_range(void){ std::vector range(2); boost::tie(range[0], range[1]) = \ - wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_RANGE]); + _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); return range; } @@ -200,13 +200,13 @@ public: } float get_rx_gain(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN]); + return _rx_subdev[SUBDEV_PROP_GAIN].as(); } std::vector get_rx_gain_range(void){ std::vector range(3); boost::tie(range[0], range[1], range[2]) = \ - wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_RANGE]); + _rx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); return range; } @@ -215,25 +215,25 @@ public: } std::string get_rx_antenna(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_ANTENNA]); + return _rx_subdev[SUBDEV_PROP_ANTENNA].as(); } std::vector get_rx_antennas(void){ - return wax::cast >(_rx_subdev[SUBDEV_PROP_ANTENNA_NAMES]); + return _rx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as >(); } /******************************************************************* * TX methods ******************************************************************/ void set_tx_rate(double rate){ - double samp_rate = wax::cast(_tx_duc[std::string("rate")]); + double samp_rate = _tx_duc[std::string("rate")].as(); assert_has(get_tx_rates(), rate, "simple device tx rate"); _tx_duc[std::string("interp")] = size_t(samp_rate/rate); } double get_tx_rate(void){ - double samp_rate = wax::cast(_tx_duc[std::string("rate")]); - size_t interp = wax::cast(_tx_duc[std::string("interp")]); + double samp_rate = _tx_duc[std::string("rate")].as(); + size_t interp = _tx_duc[std::string("interp")].as(); return samp_rate/interp; } @@ -244,7 +244,7 @@ public: tune_result_t set_tx_freq(double target_freq){ double lo_offset = 0.0; //if the local oscillator will be in the passband, use an offset - if (wax::cast(_tx_subdev[SUBDEV_PROP_LO_INTERFERES])){ + if (_tx_subdev[SUBDEV_PROP_LO_INTERFERES].as()){ lo_offset = get_tx_rate()*2.0; } return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); @@ -253,7 +253,7 @@ public: std::vector get_tx_freq_range(void){ std::vector range(2); boost::tie(range[0], range[1]) = \ - wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_RANGE]); + _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); return range; } @@ -262,13 +262,13 @@ public: } float get_tx_gain(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN]); + return _tx_subdev[SUBDEV_PROP_GAIN].as(); } std::vector get_tx_gain_range(void){ std::vector range(3); boost::tie(range[0], range[1], range[2]) = \ - wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_RANGE]); + _tx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); return range; } @@ -277,11 +277,11 @@ public: } std::string get_tx_antenna(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_ANTENNA]); + return _tx_subdev[SUBDEV_PROP_ANTENNA].as(); } std::vector get_tx_antennas(void){ - return wax::cast >(_tx_subdev[SUBDEV_PROP_ANTENNA_NAMES]); + return _tx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as >(); } private: diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index e719950e8..095b77ce1 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -98,7 +98,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case SUBDEV_PROP_NAME: val = std::string(str(boost::format("%s:%s") % dboard_id::to_string(get_rx_id()) @@ -159,14 +159,14 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case SUBDEV_PROP_GAIN: - ASSERT_THROW(wax::cast(val) == gain_t(0)); + ASSERT_THROW(val.as() == gain_t(0)); return; case SUBDEV_PROP_ANTENNA: - ASSERT_THROW(wax::cast(val) == std::string("")); + ASSERT_THROW(val.as() == std::string("")); return; case SUBDEV_PROP_ENABLED: @@ -207,7 +207,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case SUBDEV_PROP_NAME: val = dboard_id::to_string(get_tx_id()); return; @@ -265,14 +265,14 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case SUBDEV_PROP_GAIN: - ASSERT_THROW(wax::cast(val) == gain_t(0)); + ASSERT_THROW(val.as() == gain_t(0)); return; case SUBDEV_PROP_ANTENNA: - ASSERT_THROW(wax::cast(val) == std::string("")); + ASSERT_THROW(val.as() == std::string("")); return; case SUBDEV_PROP_ENABLED: diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index da05c3241..6d957436e 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -71,7 +71,7 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case DBOARD_PROP_NAME: val = std::string("usrp2 dboard (rx unit)"); return; @@ -101,7 +101,7 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case DBOARD_PROP_NAME: val = std::string("usrp2 dboard (tx unit)"); return; diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index cb7f58ec8..7520c1757 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -102,7 +102,7 @@ void usrp2_impl::update_ddc_enabled(void){ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ //handle the case where the key is an expected dsp property if (key.type() == typeid(dsp_prop_t)){ - switch(wax::cast(key)){ + switch(key.as()){ case DSP_PROP_NAME: val = std::string("usrp2 ddc0"); return; @@ -123,7 +123,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ } //handle string-based properties specific to this dsp - std::string key_name = wax::cast(key); + std::string key_name = key.as(); if (key_name == "rate"){ val = get_master_clock_freq(); return; @@ -152,9 +152,9 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ //handle string-based properties specific to this dsp - std::string key_name = wax::cast(key); + std::string key_name = key.as(); if (key_name == "decim"){ - size_t new_decim = wax::cast(val); + size_t new_decim = val.as(); assert_has( _allowed_decim_and_interp_rates, new_decim, "usrp2 decimation" @@ -164,7 +164,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ return; } else if (key_name == "freq"){ - freq_t new_freq = wax::cast(val); + freq_t new_freq = val.as(); ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); _ddc_freq = new_freq; //shadow @@ -172,13 +172,13 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ return; } else if (key_name == "enabled"){ - bool new_enabled = wax::cast(val); + bool new_enabled = val.as(); _ddc_enabled = new_enabled; //shadow update_ddc_enabled(); return; } else if (key_name == "stream_at"){ - time_spec_t new_stream_at = wax::cast(val); + time_spec_t new_stream_at = val.as(); _ddc_stream_at = new_stream_at; //shadow //update_ddc_enabled(); //dont update from here return; @@ -236,7 +236,7 @@ void usrp2_impl::update_duc_config(void){ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ //handle the case where the key is an expected dsp property if (key.type() == typeid(dsp_prop_t)){ - switch(wax::cast(key)){ + switch(key.as()){ case DSP_PROP_NAME: val = std::string("usrp2 duc0"); return; @@ -255,7 +255,7 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ } //handle string-based properties specific to this dsp - std::string key_name = wax::cast(key); + std::string key_name = key.as(); if (key_name == "rate"){ val = get_master_clock_freq(); return; @@ -280,9 +280,9 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ //handle string-based properties specific to this dsp - std::string key_name = wax::cast(key); + std::string key_name = key.as(); if (key_name == "interp"){ - size_t new_interp = wax::cast(val); + size_t new_interp = val.as(); assert_has( _allowed_decim_and_interp_rates, new_interp, "usrp2 interpolation" @@ -292,7 +292,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ return; } else if (key_name == "freq"){ - freq_t new_freq = wax::cast(val); + freq_t new_freq = val.as(); ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); _duc_freq = new_freq; //shadow diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index b66de8262..4b15c7f3e 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -91,7 +91,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ //handle the other props if (key.type() == typeid(std::string)){ - if (wax::cast(key) == "mac-addr"){ + if (key.as() == "mac-addr"){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO); @@ -105,7 +105,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; } - if (wax::cast(key) == "ip-addr"){ + if (key.as() == "ip-addr"){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); @@ -121,7 +121,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ } //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case MBOARD_PROP_NAME: val = std::string("usrp2 mboard"); return; @@ -208,11 +208,11 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //handle the other props if (key.type() == typeid(std::string)){ - if (wax::cast(key) == "mac-addr"){ + if (key.as() == "mac-addr"){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO); - mac_addr_t mac_addr(wax::cast(val)); + mac_addr_t mac_addr(val.as()); std::memcpy(out_data.data.mac_addr, &mac_addr, sizeof(mac_addr_t)); //send and recv @@ -221,11 +221,11 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; } - if (wax::cast(key) == "ip-addr"){ + if (key.as() == "ip-addr"){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO); - out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(wax::cast(val)).to_ulong()); + out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(val.as()).to_ulong()); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); @@ -235,10 +235,10 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ } //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case MBOARD_PROP_PPS_SOURCE:{ - std::string name = wax::cast(val); + std::string name = val.as(); assert_has(_pps_source_dict.get_keys(), name, "usrp2 pps source"); _pps_source = name; //shadow update_clock_config(); @@ -246,7 +246,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; case MBOARD_PROP_PPS_POLARITY:{ - std::string name = wax::cast(val); + std::string name = val.as(); assert_has(_pps_polarity_dict.get_keys(), name, "usrp2 pps polarity"); _pps_polarity = name; //shadow update_clock_config(); @@ -254,7 +254,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; case MBOARD_PROP_REF_SOURCE:{ - std::string name = wax::cast(val); + std::string name = val.as(); assert_has(_ref_source_dict.get_keys(), name, "usrp2 reference source"); _ref_source = name; //shadow update_clock_config(); @@ -262,12 +262,12 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; case MBOARD_PROP_TIME_NOW:{ - set_time_spec(wax::cast(val), true); + set_time_spec(val.as(), true); return; } case MBOARD_PROP_TIME_NEXT_PPS:{ - set_time_spec(wax::cast(val), false); + set_time_spec(val.as(), false); return; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 850a738d4..22b7e109f 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -184,7 +184,7 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case DEVICE_PROP_NAME: val = std::string("usrp2 device"); return; diff --git a/host/lib/wax.cpp b/host/lib/wax.cpp index 0348d9a66..0e2e82a3a 100644 --- a/host/lib/wax.cpp +++ b/host/lib/wax.cpp @@ -39,7 +39,7 @@ public: wax::obj & operator()(void) const{ //recursively resolve link args to get at original pointer if (_obj_ptr->type() == typeid(link_args_t)){ - return wax::cast(*_obj_ptr)(); + return _obj_ptr->as()(); } return *const_cast(_obj_ptr); } @@ -61,7 +61,7 @@ public: _obj_link = obj_ptr->get_link(); } wax::obj & operator()(void) const{ - return wax::cast(_obj_link)(); + return _obj_link.as()(); } const wax::obj & key(void) const{ return _key; @@ -94,7 +94,7 @@ wax::obj wax::obj::operator[](const obj &key){ obj val = resolve(); //check if its a special link and call if (val.type() == typeid(link_args_t)){ - return cast(val)()[key]; + return val.as()()[key]; } //unknown obj throw std::runtime_error("cannot use [] on non wax::obj link"); diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index 51497b741..a4005c0de 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -59,7 +59,7 @@ private: boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case PROP_GAIN_VALUE: val = _gain_values[name]; return; @@ -81,9 +81,9 @@ private: boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case PROP_GAIN_VALUE: - _gain_values[name] = wax::cast(val); + _gain_values[name] = val.as(); return; case PROP_GAIN_RANGE: @@ -103,14 +103,14 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ gainful_obj go0; BOOST_CHECK_THROW( - wax::cast(go0[named_prop_t(PROP_GAIN_VALUE, "fail")]), + go0[named_prop_t(PROP_GAIN_VALUE, "fail")].as(), std::exception ); std::cout << "verifying the overall min, max, step" << std::endl; gain_t gain_min, gain_max, gain_step; boost::tie(gain_min, gain_max, gain_step) = \ - wax::cast(go0[PROP_GAIN_RANGE]); + go0[PROP_GAIN_RANGE].as(); BOOST_CHECK_EQUAL(gain_min, gain_t(-10)); BOOST_CHECK_EQUAL(gain_max, gain_t(100)); BOOST_CHECK_EQUAL(gain_step, gain_t(1.5)); @@ -118,5 +118,5 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ std::cout << "verifying the overall gain" << std::endl; go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = gain_t(-5); go0[named_prop_t(PROP_GAIN_VALUE, "g1")] = gain_t(30); - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_VALUE]), gain_t(25)); + BOOST_CHECK_EQUAL(go0[PROP_GAIN_VALUE].as(), gain_t(25)); } diff --git a/host/test/wax_test.cpp b/host/test/wax_test.cpp index e5e1adc25..b793b2690 100644 --- a/host/test/wax_test.cpp +++ b/host/test/wax_test.cpp @@ -17,14 +17,15 @@ #include #include +#include enum opt_a_t{OPTION_A_0, OPTION_A_1}; enum opt_b_t{OPTION_B_0, OPTION_B_1}; BOOST_AUTO_TEST_CASE(test_enums){ wax::obj opta = OPTION_A_0; - BOOST_CHECK_THROW(wax::cast(opta), wax::bad_cast); - BOOST_CHECK_EQUAL(wax::cast(opta), OPTION_A_0); + BOOST_CHECK_THROW(opta.as(), wax::bad_cast); + BOOST_CHECK_EQUAL(opta.as(), OPTION_A_0); } /*********************************************************************** @@ -48,14 +49,14 @@ public: } void get(const wax::obj &key, wax::obj &value){ if (d_subs.size() == 0){ - value = d_nums[wax::cast(key)]; + value = d_nums[key.as()]; }else{ - value = d_subs[wax::cast(key)].get_link(); + value = d_subs[key.as()].get_link(); } } void set(const wax::obj &key, const wax::obj &value){ if (d_subs.size() == 0){ - d_nums[wax::cast(key)] = wax::cast(value); + d_nums[key.as()] = value.as(); }else{ throw std::runtime_error("cant set to a wax demo with sub demos"); } @@ -81,7 +82,7 @@ BOOST_AUTO_TEST_CASE(test_set_get){ float val = i * j * k + i + j + k; //std::cout << i << " " << j << " " << k << std::endl; wd[i][j][k] = val; - BOOST_CHECK_EQUAL(val, wax::cast(wd[i][j][k])); + BOOST_CHECK_EQUAL(val, wd[i][j][k].as()); } } } @@ -94,5 +95,5 @@ BOOST_AUTO_TEST_CASE(test_proxy){ std::cout << "assign proxy" << std::endl; wax::obj a = p[size_t(0)]; - BOOST_CHECK_EQUAL(wax::cast(a), float(5)); + BOOST_CHECK_EQUAL(a.as(), float(5)); } -- cgit v1.2.3 From 8be3b883f5b1a889f4f07611e8954449cc07c2b3 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 16 Mar 2010 13:49:39 -0700 Subject: Added ability to set the subdevices in use for rx and tx dboards. This is used to calculate and set the ddc and duc muxes. Also, minor fix for burning addrs (wrong pointer....) --- firmware/microblaze/apps/txrx.c | 11 ++++- firmware/microblaze/lib/ethernet.c | 4 +- host/include/uhd/props.hpp | 7 ++- host/lib/usrp/dboard/basic.cpp | 2 +- host/lib/usrp/dboard_manager.cpp | 4 +- host/lib/usrp/usrp2/dboard_impl.cpp | 82 ++++++++++++++++++++++++++------ host/lib/usrp/usrp2/dboard_interface.cpp | 39 ++++++++++++++- host/lib/usrp/usrp2/dboard_interface.hpp | 63 ------------------------ host/lib/usrp/usrp2/fw_common.h | 7 +++ host/lib/usrp/usrp2/usrp2_impl.hpp | 12 +++++ 10 files changed, 141 insertions(+), 90 deletions(-) delete mode 100644 host/lib/usrp/usrp2/dboard_interface.hpp (limited to 'host/lib/usrp') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 97376ffbd..8949f1263 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -427,7 +427,6 @@ void handle_udp_ctrl_packet( case USRP2_CTRL_ID_SETUP_THIS_DDC_FOR_ME_BRO: dsp_rx_regs->freq = ctrl_data_in->data.ddc_args.freq_word; dsp_rx_regs->scale_iq = ctrl_data_in->data.ddc_args.scale_iq; - dsp_rx_regs->rx_mux = 0x00 | (0x01 << 2); //TODO fill in from control //setup the interp and half band filters { @@ -471,7 +470,6 @@ void handle_udp_ctrl_packet( case USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO: dsp_tx_regs->freq = ctrl_data_in->data.duc_args.freq_word; dsp_tx_regs->scale_iq = ctrl_data_in->data.duc_args.scale_iq; - dsp_tx_regs->tx_mux = 0x01; //TODO fill in from control //setup the interp and half band filters { @@ -504,6 +502,15 @@ void handle_udp_ctrl_packet( ctrl_data_out.id = USRP2_CTRL_ID_SWEET_I_GOT_THAT_TIME_DUDE; break; + /******************************************************************* + * MUX Config + ******************************************************************/ + case USRP2_CTRL_ID_UPDATE_THOSE_MUX_SETTINGS_BRO: + dsp_rx_regs->rx_mux = ctrl_data_in->data.mux_args.rx_mux; + dsp_tx_regs->tx_mux = ctrl_data_in->data.mux_args.tx_mux; + ctrl_data_out.id = USRP2_CTRL_ID_UPDATED_THE_MUX_SETTINGS_DUDE; + break; + default: ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; diff --git a/firmware/microblaze/lib/ethernet.c b/firmware/microblaze/lib/ethernet.c index 757a36ce4..0e731c68c 100644 --- a/firmware/microblaze/lib/ethernet.c +++ b/firmware/microblaze/lib/ethernet.c @@ -316,7 +316,7 @@ ethernet_mac_addr(void) bool ethernet_set_mac_addr(const eth_mac_addr_t *t) { - bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_MAC_ADDR, &t, sizeof(eth_mac_addr_t)); + bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t)); if (ok){ src_mac_addr = *t; src_mac_addr_initialized = true; @@ -356,7 +356,7 @@ const struct ip_addr *get_ip_addr(void) } bool set_ip_addr(const struct ip_addr *t){ - bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_IP_ADDR, &t, sizeof(struct ip_addr)); + bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_IP_ADDR, t, sizeof(struct ip_addr)); if (ok){ src_ip_addr = *t; src_ip_addr_initialized = true; diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index 0dddba647..6d4414d3a 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -122,7 +122,8 @@ namespace uhd{ enum dboard_prop_t{ DBOARD_PROP_NAME, //ro, std::string DBOARD_PROP_SUBDEV, //ro, wax::obj - DBOARD_PROP_SUBDEV_NAMES //ro, prop_names_t + DBOARD_PROP_SUBDEV_NAMES, //ro, prop_names_t + DBOARD_PROP_USED_SUBDEVS //ro, prop_names_t //DBOARD_PROP_CODEC //ro, wax::obj //----> not sure, dont have to deal with yet }; @@ -135,9 +136,7 @@ namespace uhd{ CODEC_PROP_NAME, //ro, std::string CODEC_PROP_OTHERS, //ro, prop_names_t CODEC_PROP_GAIN, //rw, gain_t - CODEC_PROP_GAIN_MAX, //ro, gain_t - CODEC_PROP_GAIN_MIN, //ro, gain_t - CODEC_PROP_GAIN_STEP, //ro, gain_t + CODEC_PROP_GAIN_RANGE, //ro, gain_range_t CODEC_PROP_GAIN_NAMES, //ro, prop_names_t //CODEC_PROP_CLOCK_RATE //ro, freq_t //----> not sure we care to know };*/ diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 095b77ce1..5a82bf145 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -100,7 +100,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ case SUBDEV_PROP_NAME: - val = std::string(str(boost::format("%s:%s") + val = std::string(str(boost::format("%s - %s") % dboard_id::to_string(get_rx_id()) % get_subdev_name() )); diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index eeabbda99..6ca15e98c 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -46,7 +46,7 @@ void dboard_manager::register_dboard( //std::cout << "registering: " << name << std::endl; if (get_id_to_args_map().has_key(dboard_id)){ throw std::runtime_error(str(boost::format( - "The dboard id 0x%.4x is already registered to %s." + "The dboard id 0x%04x is already registered to %s." ) % dboard_id % dboard_id::to_string(dboard_id))); } get_id_to_args_map()[dboard_id] = args_t(dboard_ctor, name, subdev_names); @@ -54,7 +54,7 @@ void dboard_manager::register_dboard( std::string dboard_id::to_string(const dboard_id_t &id){ std::string name = (get_id_to_args_map().has_key(id))? get_id_to_args_map()[id].get<1>() : "unknown"; - return str(boost::format("%s (0x%.4x)") % name % id); + return str(boost::format("%s (0x%04x)") % name % id); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 6d957436e..502a7daa0 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -18,7 +18,6 @@ #include #include #include "usrp2_impl.hpp" -#include "dboard_interface.hpp" using namespace uhd; using namespace uhd::usrp; @@ -32,23 +31,16 @@ void usrp2_impl::dboard_init(void){ out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO); usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE); - std::cout << boost::format("rx id 0x%.2x, tx id 0x%.2x") - % ntohs(in_data.data.dboard_ids.rx_id) - % ntohs(in_data.data.dboard_ids.tx_id) << std::endl; - //extract the dboard ids an convert them to enums - dboard_id_t rx_dboard_id = static_cast( - ntohs(in_data.data.dboard_ids.rx_id) - ); - dboard_id_t tx_dboard_id = static_cast( - ntohs(in_data.data.dboard_ids.tx_id) - ); + //extract the dboard ids an convert them + dboard_id_t rx_dboard_id = ntohs(in_data.data.dboard_ids.rx_id); + dboard_id_t tx_dboard_id = ntohs(in_data.data.dboard_ids.tx_id); //create a new dboard interface and manager dboard_interface::sptr _dboard_interface( - new usrp2_dboard_interface(this) + make_usrp2_dboard_interface(this) ); - dboard_manager::sptr _dboard_manager = dboard_manager::make( + _dboard_manager = dboard_manager::make( rx_dboard_id, tx_dboard_id, _dboard_interface ); @@ -61,6 +53,46 @@ void usrp2_impl::dboard_init(void){ boost::bind(&usrp2_impl::tx_dboard_get, this, _1, _2), boost::bind(&usrp2_impl::tx_dboard_set, this, _1, _2) ); + + //init the subdevs in use (use the first subdevice) + _rx_subdevs_in_use = prop_names_t(1, _dboard_manager->get_rx_subdev_names().at(0)); + _tx_subdevs_in_use = prop_names_t(1, _dboard_manager->get_tx_subdev_names().at(0)); + update_mux_config(); +} + +void usrp2_impl::update_mux_config(void){ + //calculate the rx mux + uint32_t rx_mux = 0; + ASSERT_THROW(_rx_subdevs_in_use.size() == 1); + wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0)); + std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as() << std::endl; + if (rx_subdev[SUBDEV_PROP_QUADRATURE].as()){ + rx_mux = (0x01 << 2) | (0x00 << 0); //Q=ADC1, I=ADC0 + }else{ + rx_mux = 0x00; //ADC0 + } + if (rx_subdev[SUBDEV_PROP_IQ_SWAPPED].as()){ + rx_mux = (((rx_mux >> 0) & 0x3) << 2) | (((rx_mux >> 2) & 0x3) << 0); + } + + //calculate the tx mux + uint32_t tx_mux = 0x10; + ASSERT_THROW(_tx_subdevs_in_use.size() == 1); + wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0)); + std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as() << std::endl; + if (tx_subdev[SUBDEV_PROP_IQ_SWAPPED].as()){ + tx_mux = (((tx_mux >> 0) & 0x1) << 1) | (((tx_mux >> 1) & 0x1) << 0); + } + + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_UPDATE_THOSE_MUX_SETTINGS_BRO); + out_data.data.mux_args.rx_mux = htonl(rx_mux); + out_data.data.mux_args.tx_mux = htonl(tx_mux); + + //send and recv + usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_UPDATED_THE_MUX_SETTINGS_DUDE); } /*********************************************************************** @@ -84,12 +116,22 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_rx_subdev_names(); return; + case DBOARD_PROP_USED_SUBDEVS: + val = _rx_subdevs_in_use; + return; + //case DBOARD_PROP_CODEC: // throw std::runtime_error("unhandled prop in usrp2 dboard"); } } -void usrp2_impl::rx_dboard_set(const wax::obj &, const wax::obj &){ +void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ + if (key.as() == DBOARD_PROP_USED_SUBDEVS){ + _rx_subdevs_in_use = val.as(); + update_mux_config(); //if the val is bad, this will throw + return; + } + throw std::runtime_error("Cannot set on usrp2 dboard"); } @@ -114,11 +156,21 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_tx_subdev_names(); return; + case DBOARD_PROP_USED_SUBDEVS: + val = _tx_subdevs_in_use; + return; + //case DBOARD_PROP_CODEC: // throw std::runtime_error("unhandled prop in usrp2 dboard"); } } -void usrp2_impl::tx_dboard_set(const wax::obj &, const wax::obj &){ +void usrp2_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ + if (key.as() == DBOARD_PROP_USED_SUBDEVS){ + _tx_subdevs_in_use = val.as(); + update_mux_config(); //if the val is bad, this will throw + return; + } + throw std::runtime_error("Cannot set on usrp2 dboard"); } diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index f12b101f3..cefd69ba9 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -16,11 +16,48 @@ // #include -#include "dboard_interface.hpp" #include "usrp2_impl.hpp" using namespace uhd::usrp; +class usrp2_dboard_interface : public dboard_interface{ +public: + usrp2_dboard_interface(usrp2_impl *impl); + ~usrp2_dboard_interface(void); + + void write_aux_dac(unit_type_t, int, int); + int read_aux_adc(unit_type_t, int); + + void set_atr_reg(gpio_bank_t, uint16_t, uint16_t, uint16_t); + void set_gpio_ddr(gpio_bank_t, uint16_t, uint16_t); + void write_gpio(gpio_bank_t, uint16_t, uint16_t); + uint16_t read_gpio(gpio_bank_t); + + void write_i2c(int, const byte_vector_t &); + byte_vector_t read_i2c(int, size_t); + + double get_rx_clock_rate(void); + double get_tx_clock_rate(void); + +private: + byte_vector_t transact_spi( + spi_dev_t dev, + spi_latch_t latch, + spi_push_t push, + const byte_vector_t &buf, + bool readback + ); + + usrp2_impl *_impl; +}; + +/*********************************************************************** + * Make Function + **********************************************************************/ +dboard_interface::sptr make_usrp2_dboard_interface(usrp2_impl *impl){ + return dboard_interface::sptr(new usrp2_dboard_interface(impl)); +} + /*********************************************************************** * Structors **********************************************************************/ diff --git a/host/lib/usrp/usrp2/dboard_interface.hpp b/host/lib/usrp/usrp2/dboard_interface.hpp deleted file mode 100644 index a06359e5e..000000000 --- a/host/lib/usrp/usrp2/dboard_interface.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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 . -// - -#include - -#ifndef INCLUDED_DBOARD_INTERFACE_HPP -#define INCLUDED_DBOARD_INTERFACE_HPP - -class usrp2_impl; //dummy class declaration - -class usrp2_dboard_interface : public uhd::usrp::dboard_interface{ -public: - usrp2_dboard_interface(usrp2_impl *impl); - - ~usrp2_dboard_interface(void); - - void write_aux_dac(unit_type_t, int, int); - - int read_aux_adc(unit_type_t, int); - - void set_atr_reg(gpio_bank_t, uint16_t, uint16_t, uint16_t); - - void set_gpio_ddr(gpio_bank_t, uint16_t, uint16_t); - - void write_gpio(gpio_bank_t, uint16_t, uint16_t); - - uint16_t read_gpio(gpio_bank_t); - - void write_i2c(int, const byte_vector_t &); - - byte_vector_t read_i2c(int, size_t); - - double get_rx_clock_rate(void); - - double get_tx_clock_rate(void); - -private: - byte_vector_t transact_spi( - spi_dev_t dev, - spi_latch_t latch, - spi_push_t push, - const byte_vector_t &buf, - bool readback - ); - - usrp2_impl *_impl; -}; - -#endif /* INCLUDED_DBOARD_INTERFACE_HPP */ diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 10c1ef8cf..03e8d3a37 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -94,6 +94,9 @@ typedef enum{ USRP2_CTRL_ID_GOT_A_NEW_TIME_FOR_YOU_BRO, USRP2_CTRL_ID_SWEET_I_GOT_THAT_TIME_DUDE, + USRP2_CTRL_ID_UPDATE_THOSE_MUX_SETTINGS_BRO, + USRP2_CTRL_ID_UPDATED_THE_MUX_SETTINGS_DUDE, + USRP2_CTRL_ID_PEACE_OUT } usrp2_ctrl_id_t; @@ -194,6 +197,10 @@ typedef struct{ uint32_t ticks; uint8_t now; } time_args; + struct { + uint32_t rx_mux; + uint32_t tx_mux; + } mux_args; } data; } usrp2_ctrl_data_t; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index fc713c2bf..2c6b6f8c9 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -31,6 +31,15 @@ #ifndef INCLUDED_USRP2_IMPL_HPP #define INCLUDED_USRP2_IMPL_HPP +class usrp2_impl; //dummy class declaration + +/*! + * Make a usrp2 dboard interface. + * \param impl a pointer to the usrp2 impl object + * \return a sptr to a new dboard interface + */ +uhd::usrp::dboard_interface::sptr make_usrp2_dboard_interface(usrp2_impl *impl); + /*! * Simple wax obj proxy class: * Provides a wax obj interface for a set and a get function. @@ -156,11 +165,14 @@ private: void rx_dboard_get(const wax::obj &, wax::obj &); void rx_dboard_set(const wax::obj &, const wax::obj &); uhd::dict _rx_dboards; + uhd::prop_names_t _rx_subdevs_in_use; //properties interface for tx dboard void tx_dboard_get(const wax::obj &, wax::obj &); void tx_dboard_set(const wax::obj &, const wax::obj &); uhd::dict _tx_dboards; + uhd::prop_names_t _tx_subdevs_in_use; + void update_mux_config(void); //methods and shadows for the ddc dsp std::vector _allowed_decim_and_interp_rates; -- cgit v1.2.3 From 52dc73891474827a9c686f73cbfe70618a2dd6e4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 16 Mar 2010 15:52:56 -0700 Subject: reimplemented dict to preserve order of insertion --- host/include/uhd/dict.hpp | 43 ++++++++++++++++++------------------------ host/lib/usrp/dboard/basic.cpp | 4 ++-- 2 files changed, 20 insertions(+), 27 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/dict.hpp b/host/include/uhd/dict.hpp index 2224a0063..8f7cd5a0f 100644 --- a/host/include/uhd/dict.hpp +++ b/host/include/uhd/dict.hpp @@ -18,7 +18,7 @@ #ifndef INCLUDED_UHD_DICT_HPP #define INCLUDED_UHD_DICT_HPP -#include +#include #include #include #include @@ -27,11 +27,9 @@ namespace uhd{ /*! * A templated dictionary class with a python-like interface. - * Its wraps around a std::map internally. */ template class dict{ public: - typedef std::map map_t; typedef std::pair pair_t; /*! @@ -41,14 +39,6 @@ namespace uhd{ /* NOP */ } - /*! - * Create a dictionary from a map. - * \param map a map with key value pairs - */ - dict(const map_t &map){ - _map = map; - } - /*! * Destroy this dict. */ @@ -66,11 +56,12 @@ namespace uhd{ /*! * Get a list of the keys in this dict. + * Key order depends on insertion precedence. * \return vector of keys */ std::vector get_keys(void) const{ std::vector keys; - BOOST_FOREACH(pair_t p, _map){ + BOOST_FOREACH(const pair_t &p, _map){ keys.push_back(p.first); } return keys; @@ -78,11 +69,12 @@ namespace uhd{ /*! * Get a list of the values in this dict. + * Value order depends on insertion precedence. * \return vector of values */ std::vector get_vals(void) const{ std::vector vals; - BOOST_FOREACH(pair_t p, _map){ + BOOST_FOREACH(const pair_t &p, _map){ vals.push_back(p.second); } return vals; @@ -94,7 +86,7 @@ namespace uhd{ * \return true if found */ bool has_key(const Key &key) const{ - BOOST_FOREACH(pair_t p, _map){ + BOOST_FOREACH(const pair_t &p, _map){ if (p.first == key) return true; } return false; @@ -108,8 +100,8 @@ namespace uhd{ * \throw an exception when not found */ const Val &operator[](const Key &key) const{ - if (has_key(key)){ - return _map.find(key)->second; + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return p.second; } throw std::invalid_argument("key not found in dict"); } @@ -121,7 +113,11 @@ namespace uhd{ * \return a reference to the value */ Val &operator[](const Key &key){ - return _map[key]; + BOOST_FOREACH(pair_t &p, _map){ + if (p.first == key) return p.second; + } + _map.push_back(pair_t(key, Val())); + return _map.back().second; } /*! @@ -130,17 +126,14 @@ namespace uhd{ * \return the value of the item * \throw an exception when not found */ - Val pop_key(const Key &key){ - if (has_key(key)){ - Val val = _map.find(key)->second; - _map.erase(key); - return val; - } - throw std::invalid_argument("key not found in dict"); + Val pop(const Key &key){ + Val val = (*this)[key]; + _map.remove(pair_t(key, val)); + return val; } private: - map_t _map; //private container + std::list _map; //private container }; } //namespace uhd diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 5a82bf145..f88faf6a0 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -75,9 +75,9 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){ STATIC_BLOCK(reg_dboards){ dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX", list_of("")); - dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("a")("b")("ab")); + dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("ab")("a")("b")); dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX", list_of("")); - dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("a")("b")("ab")); + dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("ab")("a")("b")); } /*********************************************************************** -- cgit v1.2.3 From 83c463d09613b72817a837117c5f0b23975c8def Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 16 Mar 2010 19:42:38 -0700 Subject: changes to get tuning working --- host/lib/simple_device.cpp | 12 ++++++++++-- host/lib/usrp/dboard/basic.cpp | 8 ++++++-- host/lib/usrp/usrp2/io_impl.cpp | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 62a38cb79..79b035071 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -133,8 +133,16 @@ public: _mboard = (*_dev)[DEVICE_PROP_MBOARD]; _rx_ddc = _mboard[named_prop_t(MBOARD_PROP_RX_DSP, "ddc0")]; _tx_duc = _mboard[named_prop_t(MBOARD_PROP_TX_DSP, "duc0")]; - _rx_subdev = _mboard[MBOARD_PROP_RX_DBOARD][DBOARD_PROP_SUBDEV]; - _tx_subdev = _mboard[MBOARD_PROP_TX_DBOARD][DBOARD_PROP_SUBDEV]; + + //extract rx subdevice + wax::obj rx_dboard = _mboard[MBOARD_PROP_RX_DBOARD]; + std::string rx_subdev_in_use = rx_dboard[DBOARD_PROP_USED_SUBDEVS].as().at(0); + _rx_subdev = rx_dboard[named_prop_t(DBOARD_PROP_SUBDEV, rx_subdev_in_use)]; + + //extract tx subdevice + wax::obj tx_dboard = _mboard[MBOARD_PROP_TX_DBOARD]; + std::string tx_subdev_in_use = tx_dboard[DBOARD_PROP_USED_SUBDEVS].as().at(0); + _tx_subdev = tx_dboard[named_prop_t(DBOARD_PROP_SUBDEV, tx_subdev_in_use)]; } ~simple_device_impl(void){ diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index f88faf6a0..02b391244 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -172,11 +172,13 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_FREQ: + return; // it wont do you much good, but you can set it + case SUBDEV_PROP_NAME: case SUBDEV_PROP_OTHERS: case SUBDEV_PROP_GAIN_RANGE: case SUBDEV_PROP_GAIN_NAMES: - case SUBDEV_PROP_FREQ: case SUBDEV_PROP_FREQ_RANGE: case SUBDEV_PROP_ANTENNA_NAMES: case SUBDEV_PROP_QUADRATURE: @@ -278,11 +280,13 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_FREQ: + return; // it wont do you much good, but you can set it + case SUBDEV_PROP_NAME: case SUBDEV_PROP_OTHERS: case SUBDEV_PROP_GAIN_RANGE: case SUBDEV_PROP_GAIN_NAMES: - case SUBDEV_PROP_FREQ: case SUBDEV_PROP_FREQ_RANGE: case SUBDEV_PROP_ANTENNA_NAMES: case SUBDEV_PROP_QUADRATURE: diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index cc7746720..e52c1e576 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -149,7 +149,7 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ //handle the packet count / sequence number size_t expected_packet_count = _rx_stream_id_to_packet_seq[metadata.stream_id]; if (packet_count_out != expected_packet_count){ - std::cerr << "bad packet count: " << packet_count_out << std::endl; + std::cerr << "S" << (packet_count_out - expected_packet_count)%16; } _rx_stream_id_to_packet_seq[metadata.stream_id] = (packet_count_out+1)%16; -- cgit v1.2.3 From 69aaffa6d8d4614dbf6b751fe058e39fced68153 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 17 Mar 2010 17:55:20 -0800 Subject: got uhd almost compiling in windowze. figured out special flags. also had to use boost stdint because its missing in visual c++, added a bunch of numeric casts to reduce warnings --- host/CMakeLists.txt | 19 ++++-- host/include/uhd/device_addr.hpp | 5 +- host/include/uhd/metadata.hpp | 8 +-- host/include/uhd/time_spec.hpp | 8 +-- host/include/uhd/transport/vrt.hpp | 14 ++-- host/include/uhd/usrp/dboard_id.hpp | 4 +- host/include/uhd/usrp/dboard_interface.hpp | 12 ++-- host/lib/CMakeLists.txt | 5 +- host/lib/device.cpp | 2 +- host/lib/device_addr.cpp | 6 +- host/lib/time_spec.cpp | 8 +-- host/lib/transport/udp_zero_copy_none.cpp | 10 +-- host/lib/transport/vrt.cpp | 21 +++--- host/lib/usrp/usrp2/dboard_impl.cpp | 4 +- host/lib/usrp/usrp2/dboard_interface.cpp | 28 ++++---- host/lib/usrp/usrp2/dsp_impl.cpp | 23 ++++--- host/lib/usrp/usrp2/fw_common.h | 100 +++++++++++++++-------------- host/lib/usrp/usrp2/io_impl.cpp | 65 ++++++++++--------- host/lib/usrp/usrp2/usrp2_impl.hpp | 10 +-- host/test/vrt_test.cpp | 2 +- host/test/wax_test.cpp | 2 +- 21 files changed, 191 insertions(+), 165 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 30f4789a3..3576a690f 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -53,10 +53,18 @@ FUNCTION(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG flag have) ENDIF(${have}) ENDFUNCTION(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG) -UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-Wall HAVE_WALL) -UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-Wextra HAVE_WEXTRA) -UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-pedantic HAVE_PEDANTIC) -UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-ansi HAVE_ANSI) +IF(UNIX) + UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-Wall HAVE_WALL) + UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-Wextra HAVE_WEXTRA) + UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-pedantic HAVE_PEDANTIC) + UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-ansi HAVE_ANSI) +ENDIF(UNIX) + +IF(WIN32) + ADD_DEFINITIONS(-Dnot=! -Dand=&& -Dor=||) #logical operators + ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) #as requested by vs + ADD_DEFINITIONS(-DNOMINMAX) #disables stupidity and enables std::min and std::max +ENDIF(WIN32) ######################################################################## # Setup Boost @@ -64,6 +72,7 @@ UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-ansi HAVE_ANSI) FIND_PACKAGE(Boost 1.36 REQUIRED date_time program_options + regex system thread unit_test_framework @@ -78,7 +87,7 @@ LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) INCLUDE(TestBigEndian) TEST_BIG_ENDIAN(HAVE_BIG_ENDIAN) IF(HAVE_BIG_ENDIAN) - ADD_DEFINITIONS("-DHAVE_BIG_ENDIAN=/* */") + ADD_DEFINITIONS(-DHAVE_BIG_ENDIAN) ENDIF(HAVE_BIG_ENDIAN) ######################################################################## diff --git a/host/include/uhd/device_addr.hpp b/host/include/uhd/device_addr.hpp index ed538453a..1b624b770 100644 --- a/host/include/uhd/device_addr.hpp +++ b/host/include/uhd/device_addr.hpp @@ -19,10 +19,9 @@ #define INCLUDED_UHD_DEVICE_ADDR_HPP #include +#include #include #include -#include -#include #include namespace uhd{ @@ -32,7 +31,7 @@ namespace uhd{ * Provides conversion between string and binary formats. */ struct mac_addr_t{ - struct ether_addr mac_addr; + boost::uint8_t mac_addr[6]; mac_addr_t(const std::string &mac_addr_str = "00:00:00:00:00:00"); std::string to_string(void) const; }; diff --git a/host/include/uhd/metadata.hpp b/host/include/uhd/metadata.hpp index 0588ef0ed..ce72ff14b 100644 --- a/host/include/uhd/metadata.hpp +++ b/host/include/uhd/metadata.hpp @@ -28,9 +28,9 @@ namespace uhd{ * The receive routines will convert IF data headers into metadata. */ struct rx_metadata_t{ - uint32_t stream_id; - bool has_stream_id; + boost::uint32_t stream_id; time_spec_t time_spec; + bool has_stream_id; bool has_time_spec; bool is_fragment; @@ -44,9 +44,9 @@ struct rx_metadata_t{ * The send routines will convert the metadata to IF data headers. */ struct tx_metadata_t{ - uint32_t stream_id; - bool has_stream_id; + boost::uint32_t stream_id; time_spec_t time_spec; + bool has_stream_id; bool has_time_spec; bool start_of_burst; bool end_of_burst; diff --git a/host/include/uhd/time_spec.hpp b/host/include/uhd/time_spec.hpp index 7e182236b..588758824 100644 --- a/host/include/uhd/time_spec.hpp +++ b/host/include/uhd/time_spec.hpp @@ -16,7 +16,7 @@ // #include -#include +#include #ifndef INCLUDED_UHD_TIME_SPEC_HPP #define INCLUDED_UHD_TIME_SPEC_HPP @@ -30,8 +30,8 @@ namespace uhd{ * and for controlling the start of streaming for applicable dsps. */ struct time_spec_t{ - uint32_t secs; - uint32_t ticks; + boost::uint32_t secs; + boost::uint32_t ticks; /*! * Create a time_spec_t that holds a wildcard time. @@ -44,7 +44,7 @@ namespace uhd{ * \param new_secs the new seconds * \param new_ticks the new ticks (default = 0) */ - time_spec_t(uint32_t new_secs, uint32_t new_ticks = 0); + time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks = 0); /*! * Create a time_spec_t from boost posix time. diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp index 1700d2785..3b5bf41bf 100644 --- a/host/include/uhd/transport/vrt.hpp +++ b/host/include/uhd/transport/vrt.hpp @@ -38,7 +38,7 @@ namespace vrt{ */ void pack( const tx_metadata_t &metadata, //input - uint32_t *header_buff, //output + boost::uint32_t *header_buff, //output size_t &num_header_words32, //output size_t num_payload_words32, //input size_t &num_packet_words32, //output @@ -55,12 +55,12 @@ namespace vrt{ * \param packet_count the packet count sequence number */ void unpack( - rx_metadata_t &metadata, //output - const uint32_t *header_buff, //input - size_t &num_header_words32, //output - size_t &num_payload_words32, //output - size_t num_packet_words32, //input - size_t &packet_count //output + rx_metadata_t &metadata, //output + const boost::uint32_t *header_buff, //input + size_t &num_header_words32, //output + size_t &num_payload_words32, //output + size_t num_packet_words32, //input + size_t &packet_count //output ); } //namespace vrt diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 34406863d..62c61661c 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -15,15 +15,15 @@ // along with this program. If not, see . // +#include #include -#include #ifndef INCLUDED_UHD_USRP_DBOARD_ID_HPP #define INCLUDED_UHD_USRP_DBOARD_ID_HPP namespace uhd{ namespace usrp{ -typedef uint16_t dboard_id_t; +typedef boost::uint16_t dboard_id_t; static const dboard_id_t ID_NONE = 0xffff; diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index 84e1f5b22..b00643550 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -19,8 +19,8 @@ #define INCLUDED_UHD_USRP_DBOARD_INTERFACE_HPP #include +#include #include -#include namespace uhd{ namespace usrp{ @@ -33,7 +33,7 @@ namespace uhd{ namespace usrp{ class dboard_interface{ public: typedef boost::shared_ptr sptr; - typedef std::vector byte_vector_t; + typedef std::vector byte_vector_t; //tells the host which unit to use enum unit_type_t{ @@ -96,7 +96,7 @@ public: * \param rx_value 16-bits, 0=FPGA output low, 1=FPGA output high * \param mask 16-bits, 0=software, 1=atr */ - virtual void set_atr_reg(gpio_bank_t bank, uint16_t tx_value, uint16_t rx_value, uint16_t mask) = 0; + virtual void set_atr_reg(gpio_bank_t bank, boost::uint16_t tx_value, boost::uint16_t rx_value, boost::uint16_t mask) = 0; /*! * Set daughterboard GPIO data direction register. @@ -105,7 +105,7 @@ public: * \param value 16-bits, 0=FPGA input, 1=FPGA output * \param mask 16-bits, 0=ignore, 1=set */ - virtual void set_gpio_ddr(gpio_bank_t bank, uint16_t value, uint16_t mask) = 0; + virtual void set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask) = 0; /*! * Set daughterboard GPIO pin values. @@ -114,7 +114,7 @@ public: * \param value 16 bits, 0=low, 1=high * \param mask 16 bits, 0=ignore, 1=set */ - virtual void write_gpio(gpio_bank_t bank, uint16_t value, uint16_t mask) = 0; + virtual void write_gpio(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask) = 0; /*! * Read daughterboard GPIO pin values @@ -122,7 +122,7 @@ public: * \param bank GPIO_TX_BANK or GPIO_RX_BANK * \return the value of the gpio bank */ - virtual uint16_t read_gpio(gpio_bank_t bank) = 0; + virtual boost::uint16_t read_gpio(gpio_bank_t bank) = 0; /*! * \brief Write to I2C peripheral diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 1d2c5471b..46e1b0947 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -61,4 +61,7 @@ ADD_LIBRARY(uhd SHARED ${libuhd_sources}) TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES}) -INSTALL(TARGETS uhd LIBRARY DESTINATION ${LIBRARY_DIR}) +INSTALL(TARGETS uhd + LIBRARY DESTINATION ${LIBRARY_DIR} + ARCHIVE DESTINATION ${LIBRARY_DIR} +) diff --git a/host/lib/device.cpp b/host/lib/device.cpp index 897084427..cd8a01ab4 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -136,7 +136,7 @@ device::sptr device::make(const device_addr_t &hint, size_t which){ return hash_to_device[dev_hash].lock(); } //create and register a new device - catch(const std::assert_error &e){ + catch(const std::assert_error &){ device::sptr dev = maker(dev_addr); hash_to_device[dev_hash] = dev; return dev; diff --git a/host/lib/device_addr.cpp b/host/lib/device_addr.cpp index 9514df981..d26bb4b9d 100644 --- a/host/lib/device_addr.cpp +++ b/host/lib/device_addr.cpp @@ -28,7 +28,7 @@ uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){ std::string mac_addr_str = (mac_addr_str_ == "")? "ff:ff:ff:ff:ff:ff" : mac_addr_str_; //ether_aton_r(str.c_str(), &mac_addr); - uint8_t p[6] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB + boost::uint8_t p[6] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB try{ //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx @@ -43,7 +43,7 @@ uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){ int hex_num; std::istringstream iss(hex_strs[i]); iss >> std::hex >> hex_num; - p[i] = uint8_t(hex_num); + p[i] = boost::uint8_t(hex_num); } } @@ -58,7 +58,7 @@ uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){ std::string uhd::mac_addr_t::to_string(void) const{ //ether_ntoa_r(&mac_addr, addr_buf); - const uint8_t *p = reinterpret_cast(&mac_addr); + const boost::uint8_t *p = reinterpret_cast(&mac_addr); return str( boost::format("%02x:%02x:%02x:%02x:%02x:%02x") % int(p[0]) % int(p[1]) % int(p[2]) diff --git a/host/lib/time_spec.cpp b/host/lib/time_spec.cpp index 193441342..210010394 100644 --- a/host/lib/time_spec.cpp +++ b/host/lib/time_spec.cpp @@ -24,17 +24,17 @@ time_spec_t::time_spec_t(void){ ticks = ~0; } -time_spec_t::time_spec_t(uint32_t new_secs, uint32_t new_ticks){ +time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){ secs = new_secs; ticks = new_ticks; } static const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); -static double time_tick_rate(boost::posix_time::time_duration::ticks_per_second()); +static double time_tick_rate = double(boost::posix_time::time_duration::ticks_per_second()); time_spec_t::time_spec_t(boost::posix_time::ptime time, double tick_rate){ boost::posix_time::time_duration td = time - epoch; - secs = td.total_seconds(); + secs = boost::uint32_t(td.total_seconds()); double time_ticks_per_device_ticks = time_tick_rate/tick_rate; - ticks = td.fractional_seconds()/time_ticks_per_device_ticks; + ticks = boost::uint32_t(td.fractional_seconds()/time_ticks_per_device_ticks); } diff --git a/host/lib/transport/udp_zero_copy_none.cpp b/host/lib/transport/udp_zero_copy_none.cpp index e29530cf1..219ae8720 100644 --- a/host/lib/transport/udp_zero_copy_none.cpp +++ b/host/lib/transport/udp_zero_copy_none.cpp @@ -16,8 +16,10 @@ // #include +#include #include #include +#include using namespace uhd::transport; @@ -36,7 +38,7 @@ public: } ~smart_buffer_impl(void){ - delete [] boost::asio::buffer_cast(_buff); + delete [] boost::asio::buffer_cast(_buff); } const boost::asio::const_buffer &get(void) const{ @@ -89,12 +91,12 @@ udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::strin // set the rx socket buffer size: // pick a huge size, and deal with whatever we get - set_recv_buff_size(54321e3); //some big number! + set_recv_buff_size(size_t(54321e3)); //some big number! size_t current_buff_size = get_recv_buff_size(); std::cout << boost::format( "Current rx socket buffer size: %d\n" ) % current_buff_size; - if (current_buff_size < .1e6) std::cout << boost::format( + if (current_buff_size < size_t(.1e6)) std::cout << boost::format( "Adjust max rx socket buffer size (linux only):\n" " sysctl -w net.core.rmem_max=VALUE\n" ); @@ -119,7 +121,7 @@ smart_buffer::sptr udp_zero_copy_impl::recv(void){ } //allocate memory and create buffer - uint32_t *buff_mem = new uint32_t[available/sizeof(uint32_t)]; + boost::uint32_t *buff_mem = new boost::uint32_t[available/sizeof(boost::uint32_t)]; boost::asio::mutable_buffer buff(buff_mem, available); //receive only if data is available diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp index 5029df217..a06b5bf21 100644 --- a/host/lib/transport/vrt.cpp +++ b/host/lib/transport/vrt.cpp @@ -16,20 +16,21 @@ // #include -#include +#include //endianness conversion #include +using namespace uhd; using namespace uhd::transport; void vrt::pack( const tx_metadata_t &metadata, //input - uint32_t *header_buff, //output + boost::uint32_t *header_buff, //output size_t &num_header_words32, //output size_t num_payload_words32, //input size_t &num_packet_words32, //output size_t packet_count //input ){ - uint32_t vrt_hdr_flags = 0; + boost::uint32_t vrt_hdr_flags = 0; num_header_words32 = 1; //load the vrt header and flags @@ -58,18 +59,18 @@ void vrt::pack( } void vrt::unpack( - rx_metadata_t &metadata, //output - const uint32_t *header_buff, //input - size_t &num_header_words32, //output - size_t &num_payload_words32, //output - size_t num_packet_words32, //input - size_t &packet_count //output + rx_metadata_t &metadata, //output + const boost::uint32_t *header_buff, //input + size_t &num_header_words32, //output + size_t &num_payload_words32, //output + size_t num_packet_words32, //input + size_t &packet_count //output ){ //clear the metadata metadata = rx_metadata_t(); //extract vrt header - uint32_t vrt_hdr_word = ntohl(header_buff[0]); + boost::uint32_t vrt_hdr_word = ntohl(header_buff[0]); size_t packet_words32 = vrt_hdr_word & 0xffff; packet_count = (vrt_hdr_word >> 16) & 0xf; diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 502a7daa0..60622ca47 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -62,7 +62,7 @@ void usrp2_impl::dboard_init(void){ void usrp2_impl::update_mux_config(void){ //calculate the rx mux - uint32_t rx_mux = 0; + boost::uint32_t rx_mux = 0; ASSERT_THROW(_rx_subdevs_in_use.size() == 1); wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0)); std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as() << std::endl; @@ -76,7 +76,7 @@ void usrp2_impl::update_mux_config(void){ } //calculate the tx mux - uint32_t tx_mux = 0x10; + boost::uint32_t tx_mux = 0x10; ASSERT_THROW(_tx_subdevs_in_use.size() == 1); wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0)); std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as() << std::endl; diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index cefd69ba9..d20465147 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -28,10 +28,10 @@ public: void write_aux_dac(unit_type_t, int, int); int read_aux_adc(unit_type_t, int); - void set_atr_reg(gpio_bank_t, uint16_t, uint16_t, uint16_t); - void set_gpio_ddr(gpio_bank_t, uint16_t, uint16_t); - void write_gpio(gpio_bank_t, uint16_t, uint16_t); - uint16_t read_gpio(gpio_bank_t); + void set_atr_reg(gpio_bank_t, boost::uint16_t, boost::uint16_t, boost::uint16_t); + void set_gpio_ddr(gpio_bank_t, boost::uint16_t, boost::uint16_t); + void write_gpio(gpio_bank_t, boost::uint16_t, boost::uint16_t); + boost::uint16_t read_gpio(gpio_bank_t); void write_i2c(int, const byte_vector_t &); byte_vector_t read_i2c(int, size_t); @@ -89,7 +89,7 @@ double usrp2_dboard_interface::get_tx_clock_rate(void){ * \param bank the dboard interface gpio bank enum * \return an over the wire representation */ -static uint8_t gpio_bank_to_otw(dboard_interface::gpio_bank_t bank){ +static boost::uint8_t gpio_bank_to_otw(dboard_interface::gpio_bank_t bank){ switch(bank){ case uhd::usrp::dboard_interface::GPIO_TX_BANK: return USRP2_DIR_TX; case uhd::usrp::dboard_interface::GPIO_RX_BANK: return USRP2_DIR_RX; @@ -97,7 +97,7 @@ static uint8_t gpio_bank_to_otw(dboard_interface::gpio_bank_t bank){ throw std::invalid_argument("unknown gpio bank type"); } -void usrp2_dboard_interface::set_gpio_ddr(gpio_bank_t bank, uint16_t value, uint16_t mask){ +void usrp2_dboard_interface::set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_USE_THESE_GPIO_DDR_SETTINGS_BRO); @@ -110,7 +110,7 @@ void usrp2_dboard_interface::set_gpio_ddr(gpio_bank_t bank, uint16_t value, uint ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THE_GPIO_DDR_SETTINGS_DUDE); } -void usrp2_dboard_interface::write_gpio(gpio_bank_t bank, uint16_t value, uint16_t mask){ +void usrp2_dboard_interface::write_gpio(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_SET_YOUR_GPIO_PIN_OUTS_BRO); @@ -123,7 +123,7 @@ void usrp2_dboard_interface::write_gpio(gpio_bank_t bank, uint16_t value, uint16 ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_I_SET_THE_GPIO_PIN_OUTS_DUDE); } -uint16_t usrp2_dboard_interface::read_gpio(gpio_bank_t bank){ +boost::uint16_t usrp2_dboard_interface::read_gpio(gpio_bank_t bank){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_GPIO_PIN_VALS_BRO); @@ -135,7 +135,7 @@ uint16_t usrp2_dboard_interface::read_gpio(gpio_bank_t bank){ return ntohs(in_data.data.gpio_config.value); } -void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, uint16_t tx_value, uint16_t rx_value, uint16_t mask){ +void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, boost::uint16_t tx_value, boost::uint16_t rx_value, boost::uint16_t mask){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_USE_THESE_ATR_SETTINGS_BRO); @@ -158,7 +158,7 @@ void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, uint16_t tx_value, ui * \param dev the dboard interface spi dev enum * \return an over the wire representation */ -static uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ +static boost::uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ switch(dev){ case uhd::usrp::dboard_interface::SPI_TX_DEV: return USRP2_DIR_TX; case uhd::usrp::dboard_interface::SPI_RX_DEV: return USRP2_DIR_RX; @@ -172,7 +172,7 @@ static uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ * \param latch the dboard interface spi latch enum * \return an over the wire representation */ -static uint8_t spi_latch_to_otw(dboard_interface::spi_latch_t latch){ +static boost::uint8_t spi_latch_to_otw(dboard_interface::spi_latch_t latch){ switch(latch){ case uhd::usrp::dboard_interface::SPI_LATCH_RISE: return USRP2_CLK_EDGE_RISE; case uhd::usrp::dboard_interface::SPI_LATCH_FALL: return USRP2_CLK_EDGE_FALL; @@ -186,7 +186,7 @@ static uint8_t spi_latch_to_otw(dboard_interface::spi_latch_t latch){ * \param push the dboard interface spi push enum * \return an over the wire representation */ -static uint8_t spi_push_to_otw(dboard_interface::spi_push_t push){ +static boost::uint8_t spi_push_to_otw(dboard_interface::spi_push_t push){ switch(push){ case uhd::usrp::dboard_interface::SPI_PUSH_RISE: return USRP2_CLK_EDGE_RISE; case uhd::usrp::dboard_interface::SPI_PUSH_FALL: return USRP2_CLK_EDGE_FALL; @@ -286,7 +286,7 @@ dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, s * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static uint8_t spi_dev_to_otw(dboard_interface::unit_type_t unit){ +static boost::uint8_t spi_dev_to_otw(dboard_interface::unit_type_t unit){ switch(unit){ case uhd::usrp::dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; case uhd::usrp::dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; @@ -300,7 +300,7 @@ void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, i out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO); out_data.data.aux_args.dir = spi_dev_to_otw(unit); out_data.data.aux_args.which = which; - out_data.data.aux_args.dir = htonl(value); + out_data.data.aux_args.value = htonl(value); //send and recv usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 7520c1757..54ed45e41 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "usrp2_impl.hpp" using namespace uhd; @@ -25,14 +26,20 @@ using namespace uhd; static const size_t default_decim = 16; static const size_t default_interp = 16; +#define rint boost::math::iround + +template T log2(T num){ + return std::log(num)/std::log(T(2)); +} + /*********************************************************************** * DDC Helper Methods **********************************************************************/ -static uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t clock_freq){ - double scale_factor = pow(2.0, 32); +static boost::uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t clock_freq){ + double scale_factor = std::pow(2.0, 32); //calculate the freq register word - uint32_t freq_word = rint((freq / clock_freq) * scale_factor); + boost::uint32_t freq_word = rint((freq / clock_freq) * scale_factor); //update the actual frequency freq = (double(freq_word) / scale_factor) * clock_freq; @@ -40,8 +47,8 @@ static uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t return freq_word; } -static uint32_t calculate_iq_scale_word(int16_t i, int16_t q){ - return (uint16_t(i) << 16) | (uint16_t(q) << 0); +static boost::uint32_t calculate_iq_scale_word(boost::int16_t i, boost::int16_t q){ + return (boost::uint16_t(i) << 16) | (boost::uint16_t(q) << 0); } void usrp2_impl::init_ddc_config(void){ @@ -69,7 +76,7 @@ void usrp2_impl::update_ddc_config(void){ calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq()) ); out_data.data.ddc_args.decim = htonl(_ddc_decim); - static const uint32_t default_rx_scale_iq = 1024; + static const boost::int16_t default_rx_scale_iq = 1024; out_data.data.ddc_args.scale_iq = htonl( calculate_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) ); @@ -211,8 +218,8 @@ void usrp2_impl::update_duc_config(void){ while(tmp_interp > 128) tmp_interp /= 2; // Calculate closest multiplier constant to reverse gain absent scale multipliers - size_t interp_cubed = pow(tmp_interp, 3); - size_t scale = rint((4096*pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed)); + double interp_cubed = std::pow(double(tmp_interp), 3); + boost::int16_t scale = rint((4096*std::pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed)); //setup the out data usrp2_ctrl_data_t out_data; diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 03e8d3a37..9740448ee 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -24,7 +24,11 @@ * Therefore, this header may only contain valid C code. */ #ifdef __cplusplus +#include +#define _SINS_ boost:://stdint namespace when in c++ extern "C" { +#else +#include #endif // size of the vrt header and trailer to the host @@ -128,78 +132,78 @@ typedef enum{ } usrp2_clk_edge_t; typedef struct{ - uint32_t id; - uint32_t seq; + _SINS_ uint32_t id; + _SINS_ uint32_t seq; union{ - uint32_t ip_addr; - uint8_t mac_addr[6]; + _SINS_ uint32_t ip_addr; + _SINS_ uint8_t mac_addr[6]; struct { - uint16_t rx_id; - uint16_t tx_id; + _SINS_ uint16_t rx_id; + _SINS_ uint16_t tx_id; } dboard_ids; struct { - uint8_t pps_source; - uint8_t pps_polarity; - uint8_t ref_source; - uint8_t _pad; + _SINS_ uint8_t pps_source; + _SINS_ uint8_t pps_polarity; + _SINS_ uint8_t ref_source; + _SINS_ uint8_t _pad; } clock_config; struct { - uint8_t bank; - uint8_t _pad[3]; - uint16_t value; - uint16_t mask; + _SINS_ uint8_t bank; + _SINS_ uint8_t _pad[3]; + _SINS_ uint16_t value; + _SINS_ uint16_t mask; } gpio_config; struct { - uint8_t bank; - uint8_t _pad[3]; - uint16_t tx_value; - uint16_t rx_value; - uint16_t mask; + _SINS_ uint8_t bank; + _SINS_ uint8_t _pad[3]; + _SINS_ uint16_t tx_value; + _SINS_ uint16_t rx_value; + _SINS_ uint16_t mask; } atr_config; struct { - uint8_t dev; - uint8_t latch; - uint8_t push; - uint8_t readback; - uint8_t bytes; - uint8_t data[sizeof(uint32_t)]; + _SINS_ uint8_t dev; + _SINS_ uint8_t latch; + _SINS_ uint8_t push; + _SINS_ uint8_t readback; + _SINS_ uint8_t bytes; + _SINS_ uint8_t data[sizeof(_SINS_ uint32_t)]; } spi_args; struct { - uint8_t addr; - uint8_t bytes; - uint8_t data[sizeof(uint32_t)]; + _SINS_ uint8_t addr; + _SINS_ uint8_t bytes; + _SINS_ uint8_t data[sizeof(_SINS_ uint32_t)]; } i2c_args; struct { - uint8_t dir; - uint8_t which; - uint8_t _pad[2]; - uint32_t value; + _SINS_ uint8_t dir; + _SINS_ uint8_t which; + _SINS_ uint8_t _pad[2]; + _SINS_ uint32_t value; } aux_args; struct { - uint32_t freq_word; - uint32_t decim; - uint32_t scale_iq; + _SINS_ uint32_t freq_word; + _SINS_ uint32_t decim; + _SINS_ uint32_t scale_iq; } ddc_args; struct { - uint8_t enabled; - uint8_t _pad[3]; - uint32_t secs; - uint32_t ticks; - uint32_t samples; + _SINS_ uint8_t enabled; + _SINS_ uint8_t _pad[3]; + _SINS_ uint32_t secs; + _SINS_ uint32_t ticks; + _SINS_ uint32_t samples; } streaming; struct { - uint32_t freq_word; - uint32_t interp; - uint32_t scale_iq; + _SINS_ uint32_t freq_word; + _SINS_ uint32_t interp; + _SINS_ uint32_t scale_iq; } duc_args; struct { - uint32_t secs; - uint32_t ticks; - uint8_t now; + _SINS_ uint32_t secs; + _SINS_ uint32_t ticks; + _SINS_ uint8_t now; } time_args; struct { - uint32_t rx_mux; - uint32_t tx_mux; + _SINS_ uint32_t rx_mux; + _SINS_ uint32_t tx_mux; } mux_args; } data; } usrp2_ctrl_data_t; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index e52c1e576..dc8eea243 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -16,6 +16,7 @@ // #include +#include #include #include "usrp2_impl.hpp" @@ -27,11 +28,11 @@ namespace asio = boost::asio; /*********************************************************************** * Constants **********************************************************************/ -typedef std::complex fc32_t; -typedef std::complex sc16_t; +typedef std::complex fc32_t; +typedef std::complex sc16_t; -static const float shorts_per_float = pow(2.0, 15); -static const float floats_per_short = 1.0/shorts_per_float; +static const float shorts_per_float = float(1 << 15); +static const float floats_per_short = float(1.0/shorts_per_float); /*********************************************************************** * Helper Functions @@ -41,7 +42,7 @@ void usrp2_impl::io_init(void){ _rx_copy_buff = asio::buffer("", 0); //send a small data packet so the usrp2 knows the udp source port - uint32_t zero_data = 0; + boost::uint32_t zero_data = 0; _data_transport->send(asio::buffer(&zero_data, sizeof(zero_data))); } @@ -66,37 +67,37 @@ static const bool is_big_endian = false; #endif static inline void host_floats_to_usrp2_items( - uint32_t *usrp2_items, + boost::uint32_t *usrp2_items, const fc32_t *host_floats, size_t num_samps ){ unrolled_loop(i, num_samps,{ - uint16_t real = host_floats[i].real()*shorts_per_float; - uint16_t imag = host_floats[i].imag()*shorts_per_float; + boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); + boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); usrp2_items[i] = htonl((real << 16) | (imag << 0)); }); } static inline void usrp2_items_to_host_floats( fc32_t *host_floats, - const uint32_t *usrp2_items, + const boost::uint32_t *usrp2_items, size_t num_samps ){ unrolled_loop(i, num_samps,{ - uint32_t item = ntohl(usrp2_items[i]); - int16_t real = item >> 16; - int16_t imag = item >> 0; - host_floats[i] = fc32_t(real*floats_per_short, imag*floats_per_short); + boost::uint32_t item = ntohl(usrp2_items[i]); + boost::int16_t real = boost::uint16_t(item >> 16); + boost::int16_t imag = boost::uint16_t(item >> 0); + host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); }); } static inline void host_items_to_usrp2_items( - uint32_t *usrp2_items, - const uint32_t *host_items, + boost::uint32_t *usrp2_items, + const boost::uint32_t *host_items, size_t num_samps ){ if (is_big_endian){ - std::memcpy(usrp2_items, host_items, num_samps*sizeof(uint32_t)); + std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t)); } else{ unrolled_loop(i, num_samps, usrp2_items[i] = htonl(host_items[i])); @@ -104,12 +105,12 @@ static inline void host_items_to_usrp2_items( } static inline void usrp2_items_to_host_items( - uint32_t *host_items, - const uint32_t *usrp2_items, + boost::uint32_t *host_items, + const boost::uint32_t *usrp2_items, size_t num_samps ){ if (is_big_endian){ - std::memcpy(host_items, usrp2_items, num_samps*sizeof(uint32_t)); + std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t)); } else{ unrolled_loop(i, num_samps, host_items[i] = ntohl(usrp2_items[i])); @@ -124,12 +125,12 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ _rx_smart_buff = _data_transport->recv(); //unpack the vrt header - size_t num_packet_words32 = asio::buffer_size(_rx_smart_buff->get())/sizeof(uint32_t); + size_t num_packet_words32 = asio::buffer_size(_rx_smart_buff->get())/sizeof(boost::uint32_t); if (num_packet_words32 == 0){ _rx_copy_buff = boost::asio::buffer("", 0); return; //must exit here after setting the buffer } - const uint32_t *vrt_hdr = asio::buffer_cast(_rx_smart_buff->get()); + const boost::uint32_t *vrt_hdr = asio::buffer_cast(_rx_smart_buff->get()); size_t num_header_words32_out, num_payload_words32_out, packet_count_out; try{ vrt::unpack( @@ -156,7 +157,7 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ //setup the rx buffer to point to the data _rx_copy_buff = asio::buffer( vrt_hdr + num_header_words32_out, - num_payload_words32_out*sizeof(uint32_t) + num_payload_words32_out*sizeof(boost::uint32_t) ); } @@ -168,8 +169,8 @@ size_t usrp2_impl::send( const tx_metadata_t &metadata, const std::string &type ){ - uint32_t tx_mem[_mtu/sizeof(uint32_t)]; - uint32_t *items = tx_mem + vrt::max_header_words32; //offset for data + boost::uint32_t tx_mem[_mtu/sizeof(boost::uint32_t)]; + boost::uint32_t *items = tx_mem + vrt::max_header_words32; //offset for data size_t num_samps = _max_tx_samples_per_packet; //calculate the number of samples to be copied @@ -180,13 +181,13 @@ size_t usrp2_impl::send( } else if (type == "16sc"){ num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps); - host_items_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); + host_items_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); } else{ throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type)); } - uint32_t vrt_hdr[vrt::max_header_words32]; + boost::uint32_t vrt_hdr[vrt::max_header_words32]; size_t num_header_words32, num_packet_words32; size_t packet_count = _tx_stream_id_to_packet_seq[metadata.stream_id]++; @@ -202,10 +203,10 @@ size_t usrp2_impl::send( //copy in the vrt header (yes we left space) items -= num_header_words32; - std::memcpy(items, vrt_hdr, num_header_words32*sizeof(uint32_t)); + std::memcpy(items, vrt_hdr, num_header_words32*sizeof(boost::uint32_t)); //send and return number of samples - _data_transport->send(asio::buffer(items, num_packet_words32*sizeof(uint32_t))); + _data_transport->send(asio::buffer(items, num_packet_words32*sizeof(boost::uint32_t))); return num_samps; } @@ -231,8 +232,8 @@ size_t usrp2_impl::recv( //and a pointer into the usrp2 received items memory size_t bytes_to_copy = asio::buffer_size(_rx_copy_buff); if (bytes_to_copy == 0) return 0; //nothing to receive - size_t num_samps = bytes_to_copy/sizeof(uint32_t); - const uint32_t *items = asio::buffer_cast(_rx_copy_buff); + size_t num_samps = bytes_to_copy/sizeof(boost::uint32_t); + const boost::uint32_t *items = asio::buffer_cast(_rx_copy_buff); //calculate the number of samples to be copied //and copy the samples from the recv buffer @@ -242,7 +243,7 @@ size_t usrp2_impl::recv( } else if (type == "16sc"){ num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps); - usrp2_items_to_host_items(asio::buffer_cast(buff), items, num_samps); + usrp2_items_to_host_items(asio::buffer_cast(buff), items, num_samps); } else{ throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%s\"") % type)); @@ -250,7 +251,7 @@ size_t usrp2_impl::recv( //update the rx copy buffer to reflect the bytes copied _rx_copy_buff = asio::buffer( - items + num_samps, bytes_to_copy - num_samps*sizeof(uint32_t) + items + num_samps, bytes_to_copy - num_samps*sizeof(boost::uint32_t) ); return num_samps; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 2c6b6f8c9..765c523fe 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -115,17 +115,17 @@ public: private: //the raw io interface (samples are in the usrp2 native format) void recv_raw(uhd::rx_metadata_t &); - uhd::dict _tx_stream_id_to_packet_seq; - uhd::dict _rx_stream_id_to_packet_seq; + uhd::dict _tx_stream_id_to_packet_seq; + uhd::dict _rx_stream_id_to_packet_seq; static const size_t _mtu = 1500; //FIXME we have no idea static const size_t _hdrs = (2 + 14 + 20 + 8); //size of headers (pad, eth, ip, udp) static const size_t _max_rx_samples_per_packet = - (_mtu - _hdrs)/sizeof(uint32_t) - + (_mtu - _hdrs)/sizeof(boost::uint32_t) - USRP2_HOST_RX_VRT_HEADER_WORDS32 - USRP2_HOST_RX_VRT_TRAILER_WORDS32 ; static const size_t _max_tx_samples_per_packet = - (_mtu - _hdrs)/sizeof(uint32_t) - + (_mtu - _hdrs)/sizeof(boost::uint32_t) - uhd::transport::vrt::max_header_words32 ; uhd::transport::smart_buffer::sptr _rx_smart_buff; @@ -137,7 +137,7 @@ private: uhd::transport::udp_zero_copy::sptr _data_transport; //private vars for dealing with send/recv control - uint32_t _ctrl_seq_num; + boost::uint32_t _ctrl_seq_num; boost::mutex _ctrl_mutex; //methods and shadows for clock configuration diff --git a/host/test/vrt_test.cpp b/host/test/vrt_test.cpp index d80908c74..40116e110 100644 --- a/host/test/vrt_test.cpp +++ b/host/test/vrt_test.cpp @@ -25,7 +25,7 @@ static void pack_and_unpack( size_t num_payload_words32, size_t packet_count ){ - uint32_t header_buff[vrt::max_header_words32]; + boost::uint32_t header_buff[vrt::max_header_words32]; size_t num_header_words32; size_t num_packet_words32; diff --git a/host/test/wax_test.cpp b/host/test/wax_test.cpp index b793b2690..cb3b12052 100644 --- a/host/test/wax_test.cpp +++ b/host/test/wax_test.cpp @@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(test_set_get){ for (size_t i = 0; i < 10; i++){ for (size_t j = 0; j < 10; j++){ for (size_t k = 0; k < 10; k++){ - float val = i * j * k + i + j + k; + float val = float(i * j * k + i + j + k); //std::cout << i << " " << j << " " << k << std::endl; wd[i][j][k] = val; BOOST_CHECK_EQUAL(val, wd[i][j][k].as()); -- cgit v1.2.3 From f2a86eb6389210a8ebd475782ab707f814c6e49c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 18 Mar 2010 10:01:09 -0700 Subject: define namespace hack when in c compiling --- host/lib/usrp/usrp2/fw_common.h | 1 + 1 file changed, 1 insertion(+) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 9740448ee..7fcae6fb2 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -29,6 +29,7 @@ extern "C" { #else #include +#define _SINS_ #endif // size of the vrt header and trailer to the host -- cgit v1.2.3 From 10ee8022dd22f13f942d8bfeeca3b380224fff52 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 18 Mar 2010 19:38:06 +0000 Subject: added usrp1e implementation skeleton, began filling it in... --- host/include/uhd/usrp/dboard_id.hpp | 3 +- host/lib/CMakeLists.txt | 4 + host/lib/usrp/usrp1e/dboard_impl.cpp | 76 +++++++++++++++++ host/lib/usrp/usrp1e/dboard_interface.cpp | 135 ++++++++++++++++++++++++++++++ host/lib/usrp/usrp1e/dsp_impl.cpp | 63 ++++++++++++++ host/lib/usrp/usrp1e/mboard_impl.cpp | 42 ++++++++++ host/lib/usrp/usrp1e/usrp1e_impl.cpp | 33 ++++++++ host/lib/usrp/usrp1e/usrp1e_impl.hpp | 97 +++++++++++++++++++++ 8 files changed, 452 insertions(+), 1 deletion(-) create mode 100644 host/lib/usrp/usrp1e/dboard_impl.cpp create mode 100644 host/lib/usrp/usrp1e/dboard_interface.cpp create mode 100644 host/lib/usrp/usrp1e/dsp_impl.cpp create mode 100644 host/lib/usrp/usrp1e/mboard_impl.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 62c61661c..370cd1fbb 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -25,9 +25,10 @@ namespace uhd{ namespace usrp{ typedef boost::uint16_t dboard_id_t; -static const dboard_id_t ID_NONE = 0xffff; +static const dboard_id_t ID_NONE = 0xffff; //TODO: REMOVE ME namespace dboard_id{ + static const dboard_id_t NONE = 0xffff; std::string to_string(const dboard_id_t &id); } diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 7d7fcbea9..e547fef85 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -63,7 +63,11 @@ CHECK_INCLUDE_FILES( IF(HAS_USRP1E_REQUIRED_HEADERS) MESSAGE(STATUS "Building usrp1e support...") LIST(APPEND libuhd_sources + usrp/usrp1e/dboard_impl.cpp + usrp/usrp1e/dboard_interface.cpp + usrp/usrp1e/dsp_impl.cpp usrp/usrp1e/fpga-downloader.cc + usrp/usrp1e/mboard_impl.cpp usrp/usrp1e/usrp1e_impl.cpp ) ELSE(HAS_USRP1E_REQUIRED_HEADERS) diff --git a/host/lib/usrp/usrp1e/dboard_impl.cpp b/host/lib/usrp/usrp1e/dboard_impl.cpp new file mode 100644 index 000000000..7d46366bc --- /dev/null +++ b/host/lib/usrp/usrp1e/dboard_impl.cpp @@ -0,0 +1,76 @@ +// +// 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 . +// + +#include +#include +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * Dboard Initialization + **********************************************************************/ +void usrp1e_impl::dboard_init(void){ + dboard_id_t rx_dboard_id = dboard_id::NONE; //TODO get these from the eeprom + dboard_id_t tx_dboard_id = dboard_id::NONE; + + //create a new dboard interface and manager + dboard_interface::sptr dboard_interface( + make_usrp1e_dboard_interface(this) + ); + _dboard_manager = dboard_manager::make( + rx_dboard_id, tx_dboard_id, dboard_interface + ); + + //setup the dboard proxies + _rx_dboard_proxy = wax_obj_proxy( + boost::bind(&usrp1e_impl::rx_dboard_get, this, _1, _2), + boost::bind(&usrp1e_impl::rx_dboard_set, this, _1, _2) + ); + _tx_dboard_proxy = wax_obj_proxy( + boost::bind(&usrp1e_impl::tx_dboard_get, this, _1, _2), + boost::bind(&usrp1e_impl::tx_dboard_set, this, _1, _2) + ); +} + +/*********************************************************************** + * RX Dboard Get + **********************************************************************/ +void usrp1e_impl::rx_dboard_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * RX Dboard Set + **********************************************************************/ +void usrp1e_impl::rx_dboard_set(const wax::obj &, const wax::obj &){ + +} + +/*********************************************************************** + * TX Dboard Get + **********************************************************************/ +void usrp1e_impl::tx_dboard_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * TX Dboard Set + **********************************************************************/ +void usrp1e_impl::tx_dboard_set(const wax::obj &, const wax::obj &){ + +} diff --git a/host/lib/usrp/usrp1e/dboard_interface.cpp b/host/lib/usrp/usrp1e/dboard_interface.cpp new file mode 100644 index 000000000..b3e06f7be --- /dev/null +++ b/host/lib/usrp/usrp1e/dboard_interface.cpp @@ -0,0 +1,135 @@ +// +// 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 . +// + +#include +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +class usrp1e_dboard_interface : public dboard_interface{ +public: + usrp1e_dboard_interface(usrp1e_impl *impl); + ~usrp1e_dboard_interface(void); + + void write_aux_dac(unit_type_t, int, int); + int read_aux_adc(unit_type_t, int); + + void set_atr_reg(gpio_bank_t, boost::uint16_t, boost::uint16_t, boost::uint16_t); + void set_gpio_ddr(gpio_bank_t, boost::uint16_t, boost::uint16_t); + void write_gpio(gpio_bank_t, boost::uint16_t, boost::uint16_t); + boost::uint16_t read_gpio(gpio_bank_t); + + void write_i2c(int, const byte_vector_t &); + byte_vector_t read_i2c(int, size_t); + + double get_rx_clock_rate(void); + double get_tx_clock_rate(void); + +private: + byte_vector_t transact_spi( + spi_dev_t dev, + spi_latch_t latch, + spi_push_t push, + const byte_vector_t &buf, + bool readback + ); + + usrp1e_impl *_impl; +}; + +/*********************************************************************** + * Make Function + **********************************************************************/ +dboard_interface::sptr make_usrp1e_dboard_interface(usrp1e_impl *impl){ + return dboard_interface::sptr(new usrp1e_dboard_interface(impl)); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp1e_dboard_interface::usrp1e_dboard_interface(usrp1e_impl *impl){ + _impl = impl; +} + +usrp1e_dboard_interface::~usrp1e_dboard_interface(void){ + /* NOP */ +} + +/*********************************************************************** + * Clock Rates + **********************************************************************/ +double usrp1e_dboard_interface::get_rx_clock_rate(void){ + throw std::runtime_error("not implemented"); +} + +double usrp1e_dboard_interface::get_tx_clock_rate(void){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * GPIO + **********************************************************************/ +void usrp1e_dboard_interface::set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask){ + throw std::runtime_error("not implemented"); +} + +void usrp1e_dboard_interface::write_gpio(gpio_bank_t bank, boost::uint16_t value, boost::uint16_t mask){ + throw std::runtime_error("not implemented"); +} + +boost::uint16_t usrp1e_dboard_interface::read_gpio(gpio_bank_t bank){ + throw std::runtime_error("not implemented"); +} + +void usrp1e_dboard_interface::set_atr_reg(gpio_bank_t bank, boost::uint16_t tx_value, boost::uint16_t rx_value, boost::uint16_t mask){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * SPI + **********************************************************************/ +dboard_interface::byte_vector_t usrp1e_dboard_interface::transact_spi( + spi_dev_t dev, + spi_latch_t latch, + spi_push_t push, + const byte_vector_t &buf, + bool readback +){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * I2C + **********************************************************************/ +void usrp1e_dboard_interface::write_i2c(int i2c_addr, const byte_vector_t &buf){ + throw std::runtime_error("not implemented"); +} + +dboard_interface::byte_vector_t usrp1e_dboard_interface::read_i2c(int i2c_addr, size_t num_bytes){ + throw std::runtime_error("not implemented"); +} + +/*********************************************************************** + * Aux DAX/ADC + **********************************************************************/ +void usrp1e_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, int which, int value){ + throw std::runtime_error("not implemented"); +} + +int usrp1e_dboard_interface::read_aux_adc(dboard_interface::unit_type_t unit, int which){ + throw std::runtime_error("not implemented"); +} diff --git a/host/lib/usrp/usrp1e/dsp_impl.cpp b/host/lib/usrp/usrp1e/dsp_impl.cpp new file mode 100644 index 000000000..b6076ef97 --- /dev/null +++ b/host/lib/usrp/usrp1e/dsp_impl.cpp @@ -0,0 +1,63 @@ +// +// 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 . +// + +#include +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * RX DDC Initialization + **********************************************************************/ +void usrp1e_impl::rx_ddc_init(void){ + +} + +/*********************************************************************** + * RX DDC Get + **********************************************************************/ +void usrp1e_impl::rx_ddc_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * RX DDC Set + **********************************************************************/ +void usrp1e_impl::rx_ddc_set(const wax::obj &, const wax::obj &){ + +} + +/*********************************************************************** + * TX DUC Initialization + **********************************************************************/ +void usrp1e_impl::tx_duc_init(void){ + +} + +/*********************************************************************** + * TX DUC Get + **********************************************************************/ +void usrp1e_impl::tx_duc_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * TX DUC Set + **********************************************************************/ +void usrp1e_impl::tx_duc_set(const wax::obj &, const wax::obj &){ + +} diff --git a/host/lib/usrp/usrp1e/mboard_impl.cpp b/host/lib/usrp/usrp1e/mboard_impl.cpp new file mode 100644 index 000000000..c79ed1820 --- /dev/null +++ b/host/lib/usrp/usrp1e/mboard_impl.cpp @@ -0,0 +1,42 @@ +// +// 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 . +// + +#include +#include "usrp1e_impl.hpp" + +using namespace uhd::usrp; + +/*********************************************************************** + * Mboard Initialization + **********************************************************************/ +void usrp1e_impl::mboard_init(void){ + +} + +/*********************************************************************** + * Mboard Get + **********************************************************************/ +void usrp1e_impl::mboard_get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * Mboard Set + **********************************************************************/ +void usrp1e_impl::mboard_set(const wax::obj &, const wax::obj &){ + +} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.cpp b/host/lib/usrp/usrp1e/usrp1e_impl.cpp index 441f6d060..14c4b7278 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.cpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.cpp @@ -70,3 +70,36 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ device::sptr usrp1e::make(const device_addr_t &){ throw std::runtime_error("not implemented yet"); } + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp1e_impl::usrp1e_impl(void){ + //initialize the mboard + mboard_init(); + + //initialize the dboards + dboard_init(); + + //initialize the dsps + rx_ddc_init(); + tx_duc_init(); +} + +usrp1e_impl::~usrp1e_impl(void){ + /* NOP */ +} + +/*********************************************************************** + * Device Get + **********************************************************************/ +void usrp1e_impl::get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * Device Set + **********************************************************************/ +void usrp1e_impl::set(const wax::obj &, const wax::obj &){ + +} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.hpp b/host/lib/usrp/usrp1e/usrp1e_impl.hpp index 3f5f89ec6..3b2fcdd57 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.hpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -16,8 +16,105 @@ // #include +#include #ifndef INCLUDED_USRP1E_IMPL_HPP #define INCLUDED_USRP1E_IMPL_HPP +class usrp1e_impl; // dummy class declaration + +/*! + * Make a usrp1e dboard interface. + * \param impl a pointer to the usrp1e impl object + * \return a sptr to a new dboard interface + */ +uhd::usrp::dboard_interface::sptr make_usrp1e_dboard_interface(usrp1e_impl *impl); + +/*! + * Simple wax obj proxy class: + * Provides a wax obj interface for a set and a get function. + * This allows us to create nested properties structures + * while maintaining flattened code within the implementation. + */ +class wax_obj_proxy : public wax::obj{ +public: + typedef boost::function get_t; + typedef boost::function set_t; + + wax_obj_proxy(void){ + /* NOP */ + } + + wax_obj_proxy(const get_t &get, const set_t &set){ + _get = get; + _set = set; + }; + + ~wax_obj_proxy(void){ + /* NOP */ + } + + void get(const wax::obj &key, wax::obj &val){ + return _get(key, val); + } + + void set(const wax::obj &key, const wax::obj &val){ + return _set(key, val); + } + +private: + get_t _get; + set_t _set; +}; + +/*! + * USRP1E implementation guts: + * The implementation details are encapsulated here. + * Handles properties on the mboard, dboard, dsps... + */ +class usrp1e_impl : public uhd::device{ +public: + typedef boost::shared_ptr sptr; + + usrp1e_impl(void); + ~usrp1e_impl(void); + +private: + //device functions and settings + void get(const wax::obj &, wax::obj &); + void set(const wax::obj &, const wax::obj &); + + //mboard functions and settings + void mboard_init(void); + void mboard_get(const wax::obj &, wax::obj &); + void mboard_set(const wax::obj &, const wax::obj &); + wax_obj_proxy _mboard_proxy; + + //xx dboard functions and settings + void dboard_init(void); + uhd::usrp::dboard_manager::sptr _dboard_manager; + + //rx dboard functions and settings + void rx_dboard_get(const wax::obj &, wax::obj &); + void rx_dboard_set(const wax::obj &, const wax::obj &); + wax_obj_proxy _rx_dboard_proxy; + + //tx dboard functions and settings + void tx_dboard_get(const wax::obj &, wax::obj &); + void tx_dboard_set(const wax::obj &, const wax::obj &); + wax_obj_proxy _tx_dboard_proxy; + + //rx ddc functions and settings + void rx_ddc_init(void); + void rx_ddc_get(const wax::obj &, wax::obj &); + void rx_ddc_set(const wax::obj &, const wax::obj &); + wax_obj_proxy _rx_ddc_proxy; + + //tx duc functions and settings + void tx_duc_init(void); + void tx_duc_get(const wax::obj &, wax::obj &); + void tx_duc_set(const wax::obj &, const wax::obj &); + wax_obj_proxy _tx_duc_proxy; +}; + #endif /* INCLUDED_USRP1E_IMPL_HPP */ -- cgit v1.2.3 From 26ada5ee709fc4d7e195d19720b467c14368bc05 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 19 Mar 2010 18:08:20 -0800 Subject: added install path for dll, fixed idiotic msvc error where making a vector with proxies crashes the app, seems to be ok with the sptr fix, in other good news, discover usrps works in my vm for the usrp2 --- host/lib/CMakeLists.txt | 5 +++-- host/lib/usrp/usrp2/dboard_impl.cpp | 4 ++-- host/lib/usrp/usrp2/dsp_impl.cpp | 4 ++-- host/lib/usrp/usrp2/mboard_impl.cpp | 10 ++++----- host/lib/usrp/usrp2/usrp2_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 43 +++++++++++++++++++------------------ 6 files changed, 35 insertions(+), 33 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 8e6bd693c..875a065af 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -64,6 +64,7 @@ TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES}) SET_TARGET_PROPERTIES(uhd PROPERTIES DEFINE_SYMBOL "UHD_DLL_EXPORTS") INSTALL(TARGETS uhd - LIBRARY DESTINATION ${LIBRARY_DIR} - ARCHIVE DESTINATION ${LIBRARY_DIR} + LIBRARY DESTINATION ${LIBRARY_DIR} # .so file + ARCHIVE DESTINATION ${LIBRARY_DIR} # .lib file + RUNTIME DESTINATION ${LIBRARY_DIR} # .dll file ) diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 60622ca47..66e02d469 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -45,11 +45,11 @@ void usrp2_impl::dboard_init(void){ ); //load dboards - _rx_dboards[""] = wax_obj_proxy( + _rx_dboards[""] = wax_obj_proxy::make( boost::bind(&usrp2_impl::rx_dboard_get, this, _1, _2), boost::bind(&usrp2_impl::rx_dboard_set, this, _1, _2) ); - _tx_dboards[""] = wax_obj_proxy( + _tx_dboards[""] = wax_obj_proxy::make( boost::bind(&usrp2_impl::tx_dboard_get, this, _1, _2), boost::bind(&usrp2_impl::tx_dboard_set, this, _1, _2) ); diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 54ed45e41..34cce0afb 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -53,7 +53,7 @@ static boost::uint32_t calculate_iq_scale_word(boost::int16_t i, boost::int16_t void usrp2_impl::init_ddc_config(void){ //create the ddc in the rx dsp dict - _rx_dsps["ddc0"] = wax_obj_proxy( + _rx_dsps["ddc0"] = wax_obj_proxy::make( boost::bind(&usrp2_impl::ddc_get, this, _1, _2), boost::bind(&usrp2_impl::ddc_set, this, _1, _2) ); @@ -201,7 +201,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ **********************************************************************/ void usrp2_impl::init_duc_config(void){ //create the duc in the tx dsp dict - _tx_dsps["duc0"] = wax_obj_proxy( + _tx_dsps["duc0"] = wax_obj_proxy::make( boost::bind(&usrp2_impl::duc_get, this, _1, _2), boost::bind(&usrp2_impl::duc_set, this, _1, _2) ); diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 4b15c7f3e..4f63e6cc9 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -25,7 +25,7 @@ using namespace uhd; * Helper Methods **********************************************************************/ void usrp2_impl::mboard_init(void){ - _mboards[""] = wax_obj_proxy( + _mboards[""] = wax_obj_proxy::make( boost::bind(&usrp2_impl::mboard_get, this, _1, _2), boost::bind(&usrp2_impl::mboard_set, this, _1, _2) ); @@ -137,7 +137,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ case MBOARD_PROP_RX_DBOARD: ASSERT_THROW(_rx_dboards.has_key(name)); - val = _rx_dboards[name].get_link(); + val = _rx_dboards[name]->get_link(); return; case MBOARD_PROP_RX_DBOARD_NAMES: @@ -146,7 +146,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ case MBOARD_PROP_TX_DBOARD: ASSERT_THROW(_tx_dboards.has_key(name)); - val = _tx_dboards[name].get_link(); + val = _tx_dboards[name]->get_link(); return; case MBOARD_PROP_TX_DBOARD_NAMES: @@ -159,7 +159,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ case MBOARD_PROP_RX_DSP: ASSERT_THROW(_rx_dsps.has_key(name)); - val = _rx_dsps[name].get_link(); + val = _rx_dsps[name]->get_link(); return; case MBOARD_PROP_RX_DSP_NAMES: @@ -168,7 +168,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ case MBOARD_PROP_TX_DSP: ASSERT_THROW(_tx_dsps.has_key(name)); - val = _tx_dsps[name].get_link(); + val = _tx_dsps[name]->get_link(); return; case MBOARD_PROP_TX_DSP_NAMES: diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 22b7e109f..bdf8cc55b 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -191,7 +191,7 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ case DEVICE_PROP_MBOARD: ASSERT_THROW(_mboards.has_key(name)); - val = _mboards[name].get_link(); + val = _mboards[name]->get_link(); return; case DEVICE_PROP_MBOARD_NAMES: diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 765c523fe..59e23aba5 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -15,6 +15,9 @@ // along with this program. If not, see . // +#ifndef INCLUDED_USRP2_IMPL_HPP +#define INCLUDED_USRP2_IMPL_HPP + #include #include #include @@ -28,9 +31,6 @@ #include #include "fw_common.h" -#ifndef INCLUDED_USRP2_IMPL_HPP -#define INCLUDED_USRP2_IMPL_HPP - class usrp2_impl; //dummy class declaration /*! @@ -50,20 +50,25 @@ class wax_obj_proxy : public wax::obj{ public: typedef boost::function get_t; typedef boost::function set_t; + typedef boost::shared_ptr sptr; + + static sptr make(const get_t &get, const set_t &set){ + return sptr(new wax_obj_proxy(get, set)); + } - wax_obj_proxy(void){ + ~wax_obj_proxy(void){ /* NOP */ } +private: + get_t _get; + set_t _set; + wax_obj_proxy(const get_t &get, const set_t &set){ _get = get; _set = set; }; - ~wax_obj_proxy(void){ - /* NOP */ - } - void get(const wax::obj &key, wax::obj &val){ return _get(key, val); } @@ -71,10 +76,6 @@ public: void set(const wax::obj &key, const wax::obj &val){ return _set(key, val); } - -private: - get_t _get; - set_t _set; }; /*! @@ -98,10 +99,6 @@ public: ~usrp2_impl(void); - //properties interface - void get(const wax::obj &, wax::obj &); - void set(const wax::obj &, const wax::obj &); - //performs a control transaction usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &); @@ -113,6 +110,10 @@ public: size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &); private: + //device properties interface + void get(const wax::obj &, wax::obj &); + void set(const wax::obj &, const wax::obj &); + //the raw io interface (samples are in the usrp2 native format) void recv_raw(uhd::rx_metadata_t &); uhd::dict _tx_stream_id_to_packet_seq; @@ -159,18 +160,18 @@ private: void mboard_init(void); void mboard_get(const wax::obj &, wax::obj &); void mboard_set(const wax::obj &, const wax::obj &); - uhd::dict _mboards; + uhd::dict _mboards; //properties interface for rx dboard void rx_dboard_get(const wax::obj &, wax::obj &); void rx_dboard_set(const wax::obj &, const wax::obj &); - uhd::dict _rx_dboards; + uhd::dict _rx_dboards; uhd::prop_names_t _rx_subdevs_in_use; //properties interface for tx dboard void tx_dboard_get(const wax::obj &, wax::obj &); void tx_dboard_set(const wax::obj &, const wax::obj &); - uhd::dict _tx_dboards; + uhd::dict _tx_dboards; uhd::prop_names_t _tx_subdevs_in_use; void update_mux_config(void); @@ -193,12 +194,12 @@ private: //properties interface for ddc void ddc_get(const wax::obj &, wax::obj &); void ddc_set(const wax::obj &, const wax::obj &); - uhd::dict _rx_dsps; + uhd::dict _rx_dsps; //properties interface for duc void duc_get(const wax::obj &, wax::obj &); void duc_set(const wax::obj &, const wax::obj &); - uhd::dict _tx_dsps; + uhd::dict _tx_dsps; }; -- cgit v1.2.3 From d1ecc555e53770f1a5608000352f56f48c36c310 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 21 Mar 2010 00:58:34 -0700 Subject: Moved typedefs from props.hpp into new file types.hpp. Created structs to replace range tuples, and clock config struct. Merged clock config props into one property using config struct. Added templated dict construction to use the assign::map_list_of. Added gcc flag to set visibility to hidden and use the api macro. --- host/CMakeLists.txt | 4 +- host/include/uhd/CMakeLists.txt | 1 + host/include/uhd/dict.hpp | 13 +++ host/include/uhd/props.hpp | 33 ++----- host/include/uhd/simple_device.hpp | 26 +---- host/include/uhd/types.hpp | 83 ++++++++++++++++ host/include/uhd/utils.hpp | 5 +- host/lib/CMakeLists.txt | 3 +- host/lib/gain_handler.cpp | 28 +++--- host/lib/simple_device.cpp | 33 ++----- host/lib/transport/udp_zero_copy_asio.cpp | 154 ++++++++++++++++++++++++++++++ host/lib/transport/udp_zero_copy_none.cpp | 154 ------------------------------ host/lib/types.cpp | 57 +++++++++++ host/lib/usrp/dboard/basic.cpp | 1 + host/lib/usrp/usrp2/mboard_impl.cpp | 74 ++++++-------- host/lib/usrp/usrp2/usrp2_impl.hpp | 11 ++- host/test/gain_handler_test.cpp | 11 +-- 17 files changed, 388 insertions(+), 303 deletions(-) create mode 100644 host/include/uhd/types.hpp create mode 100644 host/lib/transport/udp_zero_copy_asio.cpp delete mode 100644 host/lib/transport/udp_zero_copy_none.cpp create mode 100644 host/lib/types.cpp (limited to 'host/lib/usrp') diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 29d721464..2f5d03f7d 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -58,11 +58,13 @@ IF(UNIX) UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-Wextra HAVE_WEXTRA) UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-pedantic HAVE_PEDANTIC) UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-ansi HAVE_ANSI) + #only export symbols that are declared to be part of the uhd api: + UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN) ENDIF(UNIX) IF(WIN32) ADD_DEFINITIONS(-Dnot=! -Dand=&& -Dor=||) #logical operators - ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) #as requested by vs + ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) #minimum version required is windows xp ADD_DEFINITIONS(-DNOMINMAX) #disables stupidity and enables std::min and std::max ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS) #avoid warnings from boost::split ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) #setup boost auto-linking in msvc diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 17c260c24..3d00462cf 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -29,6 +29,7 @@ INSTALL(FILES props.hpp simple_device.hpp time_spec.hpp + types.hpp utils.hpp wax.hpp DESTINATION ${HEADER_DIR}/uhd diff --git a/host/include/uhd/dict.hpp b/host/include/uhd/dict.hpp index 8f7cd5a0f..f08493952 100644 --- a/host/include/uhd/dict.hpp +++ b/host/include/uhd/dict.hpp @@ -39,6 +39,19 @@ namespace uhd{ /* NOP */ } + /*! + * Input iterator constructor: + * Makes boost::assign::map_list_of work. + * \param first the begin iterator + * \param last the end iterator + */ + template + dict(InputIterator first, InputIterator last){ + for(InputIterator it = first; it != last; it++){ + _map.push_back(*it); + } + } + /*! * Destroy this dict. */ diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index 7229d4a12..41e0eff63 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -18,34 +18,14 @@ #ifndef INCLUDED_UHD_PROPS_HPP #define INCLUDED_UHD_PROPS_HPP -#include -#include +#include #include -#include +#include #include +#include namespace uhd{ - //common typedefs for board properties - typedef float gain_t; - typedef double freq_t; - - //gain range tuple (min, max, step) - typedef boost::tuple gain_range_t; - - //freq range tuple (min, max) - typedef boost::tuple freq_range_t; - - //scalar types (have not used yet, dont uncomment until needed) - //typedef int int_scalar_t; - //typedef float real_scalar_t; - //typedef std::complex complex_scalar_t; - - //vector types (have not used yet, dont uncomment until needed) - //typedef std::vector int_vec_t; - //typedef std::vector real_vec_t; - //typedef std::vector complex_vec_t; - //typedef for handling named properties typedef std::vector prop_names_t; typedef boost::tuple named_prop_t; @@ -55,7 +35,8 @@ namespace uhd{ * \param key a reference to the prop object * \param name a reference to the name object */ - inline named_prop_t extract_named_prop(const wax::obj &key, const std::string &name = ""){ + inline UHD_API named_prop_t //must be exported as part of the api to work (TODO move guts to cpp file) + extract_named_prop(const wax::obj &key, const std::string &name = ""){ if (key.type() == typeid(named_prop_t)){ return key.as(); } @@ -94,10 +75,8 @@ namespace uhd{ MBOARD_PROP_RX_DBOARD_NAMES, //ro, prop_names_t MBOARD_PROP_TX_DBOARD, //ro, wax::obj MBOARD_PROP_TX_DBOARD_NAMES, //ro, prop_names_t - MBOARD_PROP_PPS_SOURCE, //rw, std::string (sma, mimo) + MBOARD_PROP_CLOCK_CONFIG, //rw, clock_config_t MBOARD_PROP_PPS_SOURCE_NAMES, //ro, prop_names_t - MBOARD_PROP_PPS_POLARITY, //rw, std::string (pos, neg) - MBOARD_PROP_REF_SOURCE, //rw, std::string (int, sma, mimo) MBOARD_PROP_REF_SOURCE_NAMES, //ro, prop_names_t MBOARD_PROP_TIME_NOW, //wo, time_spec_t MBOARD_PROP_TIME_NEXT_PPS //wo, time_spec_t diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp index b5d0fe311..ad25eccdc 100644 --- a/host/include/uhd/simple_device.hpp +++ b/host/include/uhd/simple_device.hpp @@ -20,29 +20,13 @@ #include #include +#include #include #include #include namespace uhd{ -/*! - * The tune result struct holds result of a 2-phase tuning: - * The struct hold the result of tuning the dboard as - * the target and actual intermediate frequency. - * The struct hold the result of tuning the DDC/DUC as - * the target and actual digital converter frequency. - * It also tell us weather or not the spectrum is inverted. - */ -struct UHD_API tune_result_t{ - double target_inter_freq; - double actual_inter_freq; - double target_dxc_freq; - double actual_dxc_freq; - bool spectrum_inverted; - tune_result_t(void); -}; - /*! * The simple UHD device class: * A simple device facilitates ease-of-use for most use-case scenarios. @@ -72,11 +56,11 @@ public: virtual std::vector get_rx_rates(void) = 0; virtual tune_result_t set_rx_freq(double freq) = 0; - virtual std::vector get_rx_freq_range(void) = 0; + virtual freq_range_t get_rx_freq_range(void) = 0; virtual void set_rx_gain(float gain) = 0; virtual float get_rx_gain(void) = 0; - virtual std::vector get_rx_gain_range(void) = 0; + virtual gain_range_t get_rx_gain_range(void) = 0; virtual void set_rx_antenna(const std::string &ant) = 0; virtual std::string get_rx_antenna(void) = 0; @@ -90,11 +74,11 @@ public: virtual std::vector get_tx_rates(void) = 0; virtual tune_result_t set_tx_freq(double freq) = 0; - virtual std::vector get_tx_freq_range(void) = 0; + virtual freq_range_t get_tx_freq_range(void) = 0; virtual void set_tx_gain(float gain) = 0; virtual float get_tx_gain(void) = 0; - virtual std::vector get_tx_gain_range(void) = 0; + virtual gain_range_t get_tx_gain_range(void) = 0; virtual void set_tx_antenna(const std::string &ant) = 0; virtual std::string get_tx_antenna(void) = 0; diff --git a/host/include/uhd/types.hpp b/host/include/uhd/types.hpp new file mode 100644 index 000000000..1439f57a1 --- /dev/null +++ b/host/include/uhd/types.hpp @@ -0,0 +1,83 @@ +// +// 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_TYPES_HPP +#define INCLUDED_UHD_TYPES_HPP + +#include +#include + +namespace uhd{ + + typedef float gain_t; //TODO REMOVE + typedef double freq_t; //TODO REMOVE + + /*! + * The gain range struct describes possible gain settings. + * The mimumum gain, maximum gain, and step size are in dB. + */ + struct UHD_API gain_range_t{ + float min, max, step; + gain_range_t(float min = 0.0, float max = 0.0, float step = 0.0); + }; + + /*! + * The frequency range struct describes possible frequency settings. + * Because tuning is very granular (sub-Hz), step size is not listed. + * The mimumum frequency and maximum frequency are in Hz. + */ + struct UHD_API freq_range_t{ + double min, max; + freq_range_t(double min = 0.0, double max = 0.0); + }; + + /*! + * The tune result struct holds result of a 2-phase tuning: + * The struct hold the result of tuning the dboard as + * the target and actual intermediate frequency. + * The struct hold the result of tuning the DDC/DUC as + * the target and actual digital converter frequency. + * It also tell us weather or not the spectrum is inverted. + */ + struct UHD_API tune_result_t{ + double target_inter_freq; + double actual_inter_freq; + double target_dxc_freq; + double actual_dxc_freq; + bool spectrum_inverted; + tune_result_t(void); + }; + + /*! + * Clock configuration settings: + * The source for the 10MHz reference clock. + * The source and polarity for the PPS clock. + * Possible settings for the reference and pps source + * are implementation specific motherboard properties. + * See the MBOARD_PROP_XXX_SOURCE_NAMES properties. + */ + struct clock_config_t{ + enum polarity_t {POLARITY_NEG, POLARITY_POS}; + std::string ref_source; + std::string pps_source; + polarity_t pps_polarity; + clock_config_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_HPP */ diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 995cb9926..e5333539f 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -18,10 +18,11 @@ #ifndef INCLUDED_UHD_UTILS_HPP #define INCLUDED_UHD_UTILS_HPP -#include -#include +#include #include #include +#include +#include /*! * Defines a function that implements the "construct on first use" idiom diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 875a065af..563ffb340 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -25,6 +25,7 @@ SET(libuhd_sources metadata.cpp simple_device.cpp time_spec.cpp + types.cpp wax.cpp transport/udp_simple.cpp transport/vrt.cpp @@ -44,7 +45,7 @@ SET(libuhd_sources # Conditionally add the udp sources ######################################################################## LIST(APPEND libuhd_sources - transport/udp_zero_copy_none.cpp + transport/udp_zero_copy_asio.cpp ) ######################################################################## diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index 847bc0528..7dd1547cb 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -17,10 +17,12 @@ #include #include +#include #include #include #include #include +#include #include using namespace uhd; @@ -99,12 +101,10 @@ gain_t gain_handler_impl::get_overall_gain_val(void){ gain_range_t gain_handler_impl::get_overall_gain_range(void){ gain_t gain_min = 0, gain_max = 0, gain_step = 0; BOOST_FOREACH(std::string name, get_gain_names()){ - gain_t gain_min_tmp, gain_max_tmp, gain_step_tmp; - boost::tie(gain_min_tmp, gain_max_tmp, gain_step_tmp) = \ - get_named_prop(_props.range, name); - gain_min += gain_min_tmp; - gain_max += gain_max_tmp; - gain_step = std::max(gain_step, gain_step_tmp); + gain_range_t gain_tmp = get_named_prop(_props.range, name); + gain_min += gain_tmp.min; + gain_max += gain_tmp.max; + gain_step = std::max(gain_step, gain_tmp.step); } return gain_range_t(gain_min, gain_max, gain_step); } @@ -150,12 +150,10 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) //not a wildcard... dont handle (but check name and range) if (name != ""){ assert_has(get_gain_names(), name, "gain name"); - gain_t gain_min, gain_max, gain_step; - boost::tie(gain_min, gain_max, gain_step) = \ - get_named_prop(_props.range, name); - if (gain_val > gain_max or gain_val < gain_min) throw std::range_error(str( + gain_range_t gain = get_named_prop(_props.range, name); + if (gain_val > gain.max or gain_val < gain.min) throw std::range_error(str( boost::format("A value of %f for gain %s is out of range of (%f, %f)") - % gain_val % name % gain_min % gain_max + % gain_val % name % gain.min % gain.max )); return false; } @@ -163,14 +161,12 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) //set the overall gain BOOST_FOREACH(std::string name, get_gain_names()){ //get the min, max, step for this gain name - gain_t gain_min, gain_max, gain_step; - boost::tie(gain_min, gain_max, gain_step) = \ - get_named_prop(_props.range, name); + gain_range_t gain = get_named_prop(_props.range, name); //clip g to be within the allowed range - gain_t g = std::min(std::max(gain_val, gain_min), gain_max); + gain_t g = std::min(std::max(gain_val, gain.min), gain.max); //set g to be a multiple of the step size - g -= fmod(g, gain_step); + g -= std::fmod(g, gain.step); //set g to be the new gain _link[named_prop_t(_props.value, name)] = g; //subtract g out of the total gain left to apply diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 79b035071..045318c6b 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,10 +28,6 @@ using namespace uhd; -tune_result_t::tune_result_t(void){ - /* NOP */ -} - /*********************************************************************** * Tune Helper Function **********************************************************************/ @@ -196,11 +193,8 @@ public: return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); } - std::vector get_rx_freq_range(void){ - std::vector range(2); - boost::tie(range[0], range[1]) = \ - _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); - return range; + freq_range_t get_rx_freq_range(void){ + return _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); } void set_rx_gain(float gain){ @@ -211,11 +205,8 @@ public: return _rx_subdev[SUBDEV_PROP_GAIN].as(); } - std::vector get_rx_gain_range(void){ - std::vector range(3); - boost::tie(range[0], range[1], range[2]) = \ - _rx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); - return range; + gain_range_t get_rx_gain_range(void){ + return _rx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); } void set_rx_antenna(const std::string &ant){ @@ -258,11 +249,8 @@ public: return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); } - std::vector get_tx_freq_range(void){ - std::vector range(2); - boost::tie(range[0], range[1]) = \ - _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); - return range; + freq_range_t get_tx_freq_range(void){ + return _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); } void set_tx_gain(float gain){ @@ -273,11 +261,8 @@ public: return _tx_subdev[SUBDEV_PROP_GAIN].as(); } - std::vector get_tx_gain_range(void){ - std::vector range(3); - boost::tie(range[0], range[1], range[2]) = \ - _tx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); - return range; + gain_range_t get_tx_gain_range(void){ + return _tx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); } void set_tx_antenna(const std::string &ant){ diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp new file mode 100644 index 000000000..219ae8720 --- /dev/null +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -0,0 +1,154 @@ +// +// 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 . +// + +#include +#include +#include +#include +#include + +using namespace uhd::transport; + +/*********************************************************************** + * Smart buffer implementation for udp zerocopy none + * + * This smart buffer implemention houses a const buffer. + * When the smart buffer is deleted, the buffer is freed. + * The memory in the const buffer is allocated with new [], + * and so the destructor frees the buffer with delete []. + **********************************************************************/ +class smart_buffer_impl : public smart_buffer{ +public: + smart_buffer_impl(const boost::asio::const_buffer &buff){ + _buff = buff; + } + + ~smart_buffer_impl(void){ + delete [] boost::asio::buffer_cast(_buff); + } + + const boost::asio::const_buffer &get(void) const{ + return _buff; + } + +private: + boost::asio::const_buffer _buff; +}; + +/*********************************************************************** + * UDP zero copy implementation class + * + * This is the portable zero copy implementation for systems + * where a faster, platform specific solution is not available. + * + * It uses boost asio udp sockets and the standard recv() class, + * and in-fact, is not actually doing a zero-copy implementation. + **********************************************************************/ +class udp_zero_copy_impl : public udp_zero_copy{ +public: + //structors + udp_zero_copy_impl(const std::string &addr, const std::string &port); + ~udp_zero_copy_impl(void); + + //send/recv + size_t send(const boost::asio::const_buffer &buff); + smart_buffer::sptr recv(void); + +private: + boost::asio::ip::udp::socket *_socket; + boost::asio::io_service _io_service; + + size_t get_recv_buff_size(void); + void set_recv_buff_size(size_t); +}; + +udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ + //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; + + // resolve the address + boost::asio::ip::udp::resolver resolver(_io_service); + boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); + boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); + + // Create, open, and connect the socket + _socket = new boost::asio::ip::udp::socket(_io_service); + _socket->open(boost::asio::ip::udp::v4()); + _socket->connect(receiver_endpoint); + + // set the rx socket buffer size: + // pick a huge size, and deal with whatever we get + set_recv_buff_size(size_t(54321e3)); //some big number! + size_t current_buff_size = get_recv_buff_size(); + std::cout << boost::format( + "Current rx socket buffer size: %d\n" + ) % current_buff_size; + if (current_buff_size < size_t(.1e6)) std::cout << boost::format( + "Adjust max rx socket buffer size (linux only):\n" + " sysctl -w net.core.rmem_max=VALUE\n" + ); +} + +udp_zero_copy_impl::~udp_zero_copy_impl(void){ + delete _socket; +} + +size_t udp_zero_copy_impl::send(const boost::asio::const_buffer &buff){ + return _socket->send(boost::asio::buffer(buff)); +} + +smart_buffer::sptr udp_zero_copy_impl::recv(void){ + size_t available = 0; + + //implement timeout through polling and sleeping + boost::asio::deadline_timer timer(_socket->get_io_service()); + timer.expires_from_now(boost::posix_time::milliseconds(50)); + while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){ + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + + //allocate memory and create buffer + boost::uint32_t *buff_mem = new boost::uint32_t[available/sizeof(boost::uint32_t)]; + boost::asio::mutable_buffer buff(buff_mem, available); + + //receive only if data is available + if (available){ + _socket->receive(boost::asio::buffer(buff)); + } + + //create a new smart buffer to house the data + return smart_buffer::sptr(new smart_buffer_impl(buff)); +} + +size_t udp_zero_copy_impl::get_recv_buff_size(void){ + boost::asio::socket_base::receive_buffer_size option; + _socket->get_option(option); + return option.value(); +} + +void udp_zero_copy_impl::set_recv_buff_size(size_t new_size){ + boost::asio::socket_base::receive_buffer_size option(new_size); + _socket->set_option(option); +} + +/*********************************************************************** + * UDP zero copy make function + **********************************************************************/ +udp_zero_copy::sptr udp_zero_copy::make( + const std::string &addr, const std::string &port +){ + return sptr(new udp_zero_copy_impl(addr, port)); +} diff --git a/host/lib/transport/udp_zero_copy_none.cpp b/host/lib/transport/udp_zero_copy_none.cpp deleted file mode 100644 index 219ae8720..000000000 --- a/host/lib/transport/udp_zero_copy_none.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// 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 . -// - -#include -#include -#include -#include -#include - -using namespace uhd::transport; - -/*********************************************************************** - * Smart buffer implementation for udp zerocopy none - * - * This smart buffer implemention houses a const buffer. - * When the smart buffer is deleted, the buffer is freed. - * The memory in the const buffer is allocated with new [], - * and so the destructor frees the buffer with delete []. - **********************************************************************/ -class smart_buffer_impl : public smart_buffer{ -public: - smart_buffer_impl(const boost::asio::const_buffer &buff){ - _buff = buff; - } - - ~smart_buffer_impl(void){ - delete [] boost::asio::buffer_cast(_buff); - } - - const boost::asio::const_buffer &get(void) const{ - return _buff; - } - -private: - boost::asio::const_buffer _buff; -}; - -/*********************************************************************** - * UDP zero copy implementation class - * - * This is the portable zero copy implementation for systems - * where a faster, platform specific solution is not available. - * - * It uses boost asio udp sockets and the standard recv() class, - * and in-fact, is not actually doing a zero-copy implementation. - **********************************************************************/ -class udp_zero_copy_impl : public udp_zero_copy{ -public: - //structors - udp_zero_copy_impl(const std::string &addr, const std::string &port); - ~udp_zero_copy_impl(void); - - //send/recv - size_t send(const boost::asio::const_buffer &buff); - smart_buffer::sptr recv(void); - -private: - boost::asio::ip::udp::socket *_socket; - boost::asio::io_service _io_service; - - size_t get_recv_buff_size(void); - void set_recv_buff_size(size_t); -}; - -udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ - //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; - - // resolve the address - boost::asio::ip::udp::resolver resolver(_io_service); - boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); - boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); - - // Create, open, and connect the socket - _socket = new boost::asio::ip::udp::socket(_io_service); - _socket->open(boost::asio::ip::udp::v4()); - _socket->connect(receiver_endpoint); - - // set the rx socket buffer size: - // pick a huge size, and deal with whatever we get - set_recv_buff_size(size_t(54321e3)); //some big number! - size_t current_buff_size = get_recv_buff_size(); - std::cout << boost::format( - "Current rx socket buffer size: %d\n" - ) % current_buff_size; - if (current_buff_size < size_t(.1e6)) std::cout << boost::format( - "Adjust max rx socket buffer size (linux only):\n" - " sysctl -w net.core.rmem_max=VALUE\n" - ); -} - -udp_zero_copy_impl::~udp_zero_copy_impl(void){ - delete _socket; -} - -size_t udp_zero_copy_impl::send(const boost::asio::const_buffer &buff){ - return _socket->send(boost::asio::buffer(buff)); -} - -smart_buffer::sptr udp_zero_copy_impl::recv(void){ - size_t available = 0; - - //implement timeout through polling and sleeping - boost::asio::deadline_timer timer(_socket->get_io_service()); - timer.expires_from_now(boost::posix_time::milliseconds(50)); - while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){ - boost::this_thread::sleep(boost::posix_time::milliseconds(1)); - } - - //allocate memory and create buffer - boost::uint32_t *buff_mem = new boost::uint32_t[available/sizeof(boost::uint32_t)]; - boost::asio::mutable_buffer buff(buff_mem, available); - - //receive only if data is available - if (available){ - _socket->receive(boost::asio::buffer(buff)); - } - - //create a new smart buffer to house the data - return smart_buffer::sptr(new smart_buffer_impl(buff)); -} - -size_t udp_zero_copy_impl::get_recv_buff_size(void){ - boost::asio::socket_base::receive_buffer_size option; - _socket->get_option(option); - return option.value(); -} - -void udp_zero_copy_impl::set_recv_buff_size(size_t new_size){ - boost::asio::socket_base::receive_buffer_size option(new_size); - _socket->set_option(option); -} - -/*********************************************************************** - * UDP zero copy make function - **********************************************************************/ -udp_zero_copy::sptr udp_zero_copy::make( - const std::string &addr, const std::string &port -){ - return sptr(new udp_zero_copy_impl(addr, port)); -} diff --git a/host/lib/types.cpp b/host/lib/types.cpp new file mode 100644 index 000000000..f8a9a9b36 --- /dev/null +++ b/host/lib/types.cpp @@ -0,0 +1,57 @@ +// +// 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 . +// + +#include + +using namespace uhd; + +/*********************************************************************** + * gain range + **********************************************************************/ +gain_range_t::gain_range_t(float min_, float max_, float step_){ + min = min_; + max = max_; + step = step_; +} + +/*********************************************************************** + * freq range + **********************************************************************/ +freq_range_t::freq_range_t(double min_, double max_){ + min = min_; + max = max_; +} + +/*********************************************************************** + * tune result + **********************************************************************/ +tune_result_t::tune_result_t(void){ + target_inter_freq = 0.0; + actual_inter_freq = 0.0; + target_dxc_freq = 0.0; + actual_dxc_freq = 0.0; + spectrum_inverted = false; +} + +/*********************************************************************** + * clock config + **********************************************************************/ +clock_config_t::clock_config_t(void){ + ref_source = ""; //not a valid setting + pps_source = ""; //not a valid setting + pps_polarity = POLARITY_NEG; +} diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 02b391244..82485ae6a 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 4f63e6cc9..cbca8eec7 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -16,7 +16,6 @@ // #include -#include #include "usrp2_impl.hpp" using namespace uhd; @@ -36,21 +35,27 @@ void usrp2_impl::mboard_init(void){ } void usrp2_impl::init_clock_config(void){ + //init the ref source clock config + _ref_source_dict = boost::assign::map_list_of + ("int", USRP2_REF_SOURCE_INT) + ("sma", USRP2_REF_SOURCE_SMA) + ("mimo", USRP2_REF_SOURCE_MIMO) + ; + _clock_config.ref_source = "int"; + //init the pps source clock config - _pps_source_dict["sma"] = USRP2_PPS_SOURCE_SMA; - _pps_source_dict["mimo"] = USRP2_PPS_SOURCE_MIMO; - _pps_source = "sma"; + _pps_source_dict = boost::assign::map_list_of + ("sma", USRP2_PPS_SOURCE_SMA) + ("mimo", USRP2_PPS_SOURCE_MIMO) + ; + _clock_config.pps_source = "sma"; //init the pps polarity clock config - _pps_polarity_dict["pos"] = USRP2_PPS_POLARITY_POS; - _pps_polarity_dict["neg"] = USRP2_PPS_POLARITY_NEG; - _pps_polarity = "neg"; - - //init the ref source clock config - _ref_source_dict["int"] = USRP2_REF_SOURCE_INT; - _ref_source_dict["sma"] = USRP2_REF_SOURCE_SMA; - _ref_source_dict["mimo"] = USRP2_REF_SOURCE_MIMO; - _ref_source = "int"; + _pps_polarity_dict = boost::assign::map_list_of + (clock_config_t::POLARITY_POS, USRP2_PPS_POLARITY_POS) + (clock_config_t::POLARITY_NEG, USRP2_PPS_POLARITY_NEG) + ; + _clock_config.pps_polarity = clock_config_t::POLARITY_NEG; //update the clock config (sends a control packet) update_clock_config(); @@ -60,9 +65,9 @@ void usrp2_impl::update_clock_config(void){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_HERES_A_NEW_CLOCK_CONFIG_BRO); - out_data.data.clock_config.pps_source = _pps_source_dict [_pps_source]; - out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_pps_polarity]; - out_data.data.clock_config.ref_source = _ref_source_dict [_ref_source]; + out_data.data.clock_config.ref_source = _ref_source_dict [_clock_config.ref_source]; + out_data.data.clock_config.pps_source = _pps_source_dict [_clock_config.pps_source]; + out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_clock_config.pps_polarity]; //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); @@ -175,22 +180,14 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = prop_names_t(_tx_dsps.get_keys()); return; - case MBOARD_PROP_PPS_SOURCE: - val = _pps_source; + case MBOARD_PROP_CLOCK_CONFIG: + val = _clock_config; return; case MBOARD_PROP_PPS_SOURCE_NAMES: val = prop_names_t(_pps_source_dict.get_keys()); return; - case MBOARD_PROP_PPS_POLARITY: - val = _pps_polarity; - return; - - case MBOARD_PROP_REF_SOURCE: - val = _ref_source; - return; - case MBOARD_PROP_REF_SOURCE_NAMES: val = prop_names_t(_ref_source_dict.get_keys()); return; @@ -237,26 +234,11 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ - case MBOARD_PROP_PPS_SOURCE:{ - std::string name = val.as(); - assert_has(_pps_source_dict.get_keys(), name, "usrp2 pps source"); - _pps_source = name; //shadow - update_clock_config(); - } - return; - - case MBOARD_PROP_PPS_POLARITY:{ - std::string name = val.as(); - assert_has(_pps_polarity_dict.get_keys(), name, "usrp2 pps polarity"); - _pps_polarity = name; //shadow - update_clock_config(); - } - return; - - case MBOARD_PROP_REF_SOURCE:{ - std::string name = val.as(); - assert_has(_ref_source_dict.get_keys(), name, "usrp2 reference source"); - _ref_source = name; //shadow + case MBOARD_PROP_CLOCK_CONFIG:{ + clock_config_t clock_config = val.as(); + assert_has(_pps_source_dict.get_keys(), clock_config.pps_source, "usrp2 pps source"); + assert_has(_ref_source_dict.get_keys(), clock_config.ref_source, "usrp2 ref source"); + _clock_config = clock_config; //shadow update_clock_config(); } return; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 59e23aba5..70420fd49 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -20,11 +20,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #include #include @@ -142,15 +143,15 @@ private: boost::mutex _ctrl_mutex; //methods and shadows for clock configuration - std::string _pps_source, _pps_polarity, _ref_source; + uhd::clock_config_t _clock_config; void init_clock_config(void); void update_clock_config(void); void set_time_spec(const uhd::time_spec_t &time_spec, bool now); //mappings from clock config strings to over the wire enums - uhd::dict _pps_source_dict; - uhd::dict _pps_polarity_dict; - uhd::dict _ref_source_dict; + uhd::dict _ref_source_dict; + uhd::dict _pps_source_dict; + uhd::dict _pps_polarity_dict; //rx and tx dboard methods and objects uhd::usrp::dboard_manager::sptr _dboard_manager; diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index a4005c0de..47acb30f0 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -108,12 +109,10 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ ); std::cout << "verifying the overall min, max, step" << std::endl; - gain_t gain_min, gain_max, gain_step; - boost::tie(gain_min, gain_max, gain_step) = \ - go0[PROP_GAIN_RANGE].as(); - BOOST_CHECK_EQUAL(gain_min, gain_t(-10)); - BOOST_CHECK_EQUAL(gain_max, gain_t(100)); - BOOST_CHECK_EQUAL(gain_step, gain_t(1.5)); + gain_range_t gain = go0[PROP_GAIN_RANGE].as(); + BOOST_CHECK_EQUAL(gain.min, gain_t(-10)); + BOOST_CHECK_EQUAL(gain.max, gain_t(100)); + BOOST_CHECK_EQUAL(gain.step, gain_t(1.5)); std::cout << "verifying the overall gain" << std::endl; go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = gain_t(-5); -- cgit v1.2.3 From a31761cb0c37b61f7243836d6dd8c40cbf49efc0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 22 Mar 2010 13:12:03 +0000 Subject: filled in more skeleton code, filled in dboard interface spi and i2c with ioctls, added file descriptor opening, and checking for usrp1 kernel header --- host/lib/CMakeLists.txt | 1 + host/lib/usrp/usrp1e/dboard_impl.cpp | 4 +- host/lib/usrp/usrp1e/dboard_interface.cpp | 60 +++++++++++++++++++++-- host/lib/usrp/usrp1e/dsp_impl.cpp | 11 ++++- host/lib/usrp/usrp1e/mboard_impl.cpp | 6 ++- host/lib/usrp/usrp1e/usrp1e_impl.cpp | 79 ++++++++++++++++++++++++++----- host/lib/usrp/usrp1e/usrp1e_impl.hpp | 48 ++++++++++++------- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 - 8 files changed, 172 insertions(+), 39 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a7dded86b..46cce729e 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -56,6 +56,7 @@ INCLUDE(CheckIncludeFiles) SET(usrp1e_required_headers linux/ioctl.h linux/spi/spidev.h + linux/usrp1_e.h ) CHECK_INCLUDE_FILES( "${usrp1e_required_headers}" diff --git a/host/lib/usrp/usrp1e/dboard_impl.cpp b/host/lib/usrp/usrp1e/dboard_impl.cpp index 7d46366bc..a2798dce3 100644 --- a/host/lib/usrp/usrp1e/dboard_impl.cpp +++ b/host/lib/usrp/usrp1e/dboard_impl.cpp @@ -37,11 +37,11 @@ void usrp1e_impl::dboard_init(void){ ); //setup the dboard proxies - _rx_dboard_proxy = wax_obj_proxy( + _rx_dboard_proxy = wax_obj_proxy::make( boost::bind(&usrp1e_impl::rx_dboard_get, this, _1, _2), boost::bind(&usrp1e_impl::rx_dboard_set, this, _1, _2) ); - _tx_dboard_proxy = wax_obj_proxy( + _tx_dboard_proxy = wax_obj_proxy::make( boost::bind(&usrp1e_impl::tx_dboard_get, this, _1, _2), boost::bind(&usrp1e_impl::tx_dboard_set, this, _1, _2) ); diff --git a/host/lib/usrp/usrp1e/dboard_interface.cpp b/host/lib/usrp/usrp1e/dboard_interface.cpp index b3e06f7be..ef91014ac 100644 --- a/host/lib/usrp/usrp1e/dboard_interface.cpp +++ b/host/lib/usrp/usrp1e/dboard_interface.cpp @@ -16,7 +16,9 @@ // #include +#include //std::copy #include "usrp1e_impl.hpp" +#include using namespace uhd::usrp; @@ -109,18 +111,70 @@ dboard_interface::byte_vector_t usrp1e_dboard_interface::transact_spi( const byte_vector_t &buf, bool readback ){ - throw std::runtime_error("not implemented"); + //load data struct + usrp_e_spi data; + data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; + data.slave = (dev == SPI_RX_DEV)? UE_SPI_CTRL_RXNEG : UE_SPI_CTRL_TXNEG; + data.length = buf.size() * 8; //bytes to bits + boost::uint8_t *data_bytes = reinterpret_cast(&data.data); + + //load the data + ASSERT_THROW(buf.size() <= sizeof(data.data)); + std::copy(buf.begin(), buf.end(), data_bytes); + + //load the flags + data.flags = 0; + data.flags |= (latch == SPI_LATCH_RISE)? UE_SPI_LATCH_RISE : UE_SPI_LATCH_FALL; + data.flags |= (push == SPI_PUSH_RISE)? UE_SPI_PUSH_RISE : UE_SPI_PUSH_FALL; + + //call the spi ioctl + _impl->ioctl(USRP_E_SPI, &data); + + //unload the data + byte_vector_t ret(data.length/8); //bits to bytes + ASSERT_THROW(ret.size() <= sizeof(data.data)); + std::copy(data_bytes, data_bytes+ret.size(), ret.begin()); + return ret; } /*********************************************************************** * I2C **********************************************************************/ +static const size_t max_i2c_data_bytes = 10; + void usrp1e_dboard_interface::write_i2c(int i2c_addr, const byte_vector_t &buf){ - throw std::runtime_error("not implemented"); + //allocate some memory for this transaction + ASSERT_THROW(buf.size() <= max_i2c_data_bytes); + boost::uint8_t mem[sizeof(usrp_e_i2c) + max_i2c_data_bytes]; + + //load the data struct + usrp_e_i2c &data = reinterpret_cast(mem); + data.addr = i2c_addr; + data.len = buf.size(); + std::copy(buf.begin(), buf.end(), data.data); + + //call the spi ioctl + _impl->ioctl(USRP_E_I2C_WRITE, &data); } dboard_interface::byte_vector_t usrp1e_dboard_interface::read_i2c(int i2c_addr, size_t num_bytes){ - throw std::runtime_error("not implemented"); + //allocate some memory for this transaction + ASSERT_THROW(num_bytes <= max_i2c_data_bytes); + boost::uint8_t mem[sizeof(usrp_e_i2c) + max_i2c_data_bytes]; + + //load the data struct + usrp_e_i2c &data = reinterpret_cast(mem); + data.addr = i2c_addr; + data.len = num_bytes; + + //call the spi ioctl + _impl->ioctl(USRP_E_I2C_READ, &data); + + //unload the data + byte_vector_t ret(data.len); + ASSERT_THROW(ret.size() == num_bytes); + std::copy(data.data, data.data+ret.size(), ret.begin()); + return ret; } /*********************************************************************** diff --git a/host/lib/usrp/usrp1e/dsp_impl.cpp b/host/lib/usrp/usrp1e/dsp_impl.cpp index b6076ef97..862b89184 100644 --- a/host/lib/usrp/usrp1e/dsp_impl.cpp +++ b/host/lib/usrp/usrp1e/dsp_impl.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include #include #include "usrp1e_impl.hpp" @@ -24,7 +25,10 @@ using namespace uhd::usrp; * RX DDC Initialization **********************************************************************/ void usrp1e_impl::rx_ddc_init(void){ - + _rx_ddc_proxy = wax_obj_proxy::make( + boost::bind(&usrp1e_impl::rx_ddc_get, this, _1, _2), + boost::bind(&usrp1e_impl::rx_ddc_set, this, _1, _2) + ); } /*********************************************************************** @@ -45,7 +49,10 @@ void usrp1e_impl::rx_ddc_set(const wax::obj &, const wax::obj &){ * TX DUC Initialization **********************************************************************/ void usrp1e_impl::tx_duc_init(void){ - + _tx_duc_proxy = wax_obj_proxy::make( + boost::bind(&usrp1e_impl::tx_duc_get, this, _1, _2), + boost::bind(&usrp1e_impl::tx_duc_set, this, _1, _2) + ); } /*********************************************************************** diff --git a/host/lib/usrp/usrp1e/mboard_impl.cpp b/host/lib/usrp/usrp1e/mboard_impl.cpp index c79ed1820..b480f7616 100644 --- a/host/lib/usrp/usrp1e/mboard_impl.cpp +++ b/host/lib/usrp/usrp1e/mboard_impl.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include #include #include "usrp1e_impl.hpp" @@ -24,7 +25,10 @@ using namespace uhd::usrp; * Mboard Initialization **********************************************************************/ void usrp1e_impl::mboard_init(void){ - + _mboard_proxy = wax_obj_proxy::make( + boost::bind(&usrp1e_impl::mboard_get, this, _1, _2), + boost::bind(&usrp1e_impl::mboard_set, this, _1, _2) + ); } /*********************************************************************** diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.cpp b/host/lib/usrp/usrp1e/usrp1e_impl.cpp index 14c4b7278..d3b0264a7 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.cpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.cpp @@ -19,9 +19,12 @@ #include #include #include "usrp1e_impl.hpp" +#include //open +#include //ioctl using namespace uhd; using namespace uhd::usrp; +namespace fs = boost::filesystem; STATIC_BLOCK(register_usrp1e_device){ device::register_device(&usrp1e::discover, &usrp1e::make); @@ -30,8 +33,8 @@ STATIC_BLOCK(register_usrp1e_device){ /*********************************************************************** * Helper Functions **********************************************************************/ -static bool file_exists(const std::string &file_path){ - return boost::filesystem::exists(file_path); +static std::string abs_path(const std::string &file_path){ + return fs::system_complete(fs::path(file_path)).file_string(); } /*********************************************************************** @@ -42,10 +45,10 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ //if a node was provided, use it and only it if (device_addr.has_key("node")){ - if (not file_exists(device_addr["node"])) return usrp1e_addrs; + if (not fs::exists(device_addr["node"])) return usrp1e_addrs; device_addr_t new_addr; new_addr["name"] = "USRP1E"; - new_addr["node"] = device_addr["node"]; + new_addr["node"] = abs_path(device_addr["node"]); usrp1e_addrs.push_back(new_addr); } @@ -53,10 +56,10 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ else{ for(size_t i = 0; i < 5; i++){ std::string node = str(boost::format("/dev/usrp1_e%d") % i); - if (not file_exists(node)) continue; + if (not fs::exists(node)) continue; device_addr_t new_addr; new_addr["name"] = "USRP1E"; - new_addr["node"] = node; + new_addr["node"] = abs_path(node); usrp1e_addrs.push_back(new_addr); } } @@ -67,14 +70,23 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ /*********************************************************************** * Make **********************************************************************/ -device::sptr usrp1e::make(const device_addr_t &){ - throw std::runtime_error("not implemented yet"); +device::sptr usrp1e::make(const device_addr_t &device_addr){ + std::string node = device_addr["node"]; + int node_fd = open(node.c_str(), 0); + if (node_fd < 0){ + throw std::runtime_error(str( + boost::format("Failed to open %s") % node + )); + } + return sptr(new usrp1e_impl(node_fd)); } /*********************************************************************** * Structors **********************************************************************/ -usrp1e_impl::usrp1e_impl(void){ +usrp1e_impl::usrp1e_impl(int node_fd){ + _node_fd = node_fd; + //initialize the mboard mboard_init(); @@ -90,16 +102,59 @@ usrp1e_impl::~usrp1e_impl(void){ /* NOP */ } +/*********************************************************************** + * Misc Methods + **********************************************************************/ +void usrp1e_impl::ioctl(int request, void *mem){ + if (::ioctl(_node_fd, request, mem) < 0){ + throw std::runtime_error(str( + boost::format("ioctl failed with request %d") % request + )); + } +} + /*********************************************************************** * Device Get **********************************************************************/ -void usrp1e_impl::get(const wax::obj &, wax::obj &){ - +void usrp1e_impl::get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case DEVICE_PROP_NAME: + val = std::string("usrp1e device"); + return; + + case DEVICE_PROP_MBOARD: + ASSERT_THROW(name == ""); + val = _mboard_proxy->get_link(); + return; + + case DEVICE_PROP_MBOARD_NAMES: + val = prop_names_t(1, ""); //vector of size 1 with empty string + return; + + case DEVICE_PROP_MAX_RX_SAMPLES: + val = size_t(0); //TODO + return; + + case DEVICE_PROP_MAX_TX_SAMPLES: + val = size_t(0); //TODO + return; + + } } /*********************************************************************** * Device Set **********************************************************************/ void usrp1e_impl::set(const wax::obj &, const wax::obj &){ - + throw std::runtime_error("Cannot set in usrp1e device"); } + +/*********************************************************************** + * Device IO (TODO) + **********************************************************************/ +size_t usrp1e_impl::send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &){return 0;} +size_t usrp1e_impl::recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &){return 0;} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.hpp b/host/lib/usrp/usrp1e/usrp1e_impl.hpp index 3b2fcdd57..7a09254ec 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.hpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -40,20 +40,25 @@ class wax_obj_proxy : public wax::obj{ public: typedef boost::function get_t; typedef boost::function set_t; + typedef boost::shared_ptr sptr; - wax_obj_proxy(void){ + static sptr make(const get_t &get, const set_t &set){ + return sptr(new wax_obj_proxy(get, set)); + } + + ~wax_obj_proxy(void){ /* NOP */ } +private: + get_t _get; + set_t _set; + wax_obj_proxy(const get_t &get, const set_t &set){ _get = get; _set = set; }; - ~wax_obj_proxy(void){ - /* NOP */ - } - void get(const wax::obj &key, wax::obj &val){ return _get(key, val); } @@ -61,10 +66,6 @@ public: void set(const wax::obj &key, const wax::obj &val){ return _set(key, val); } - -private: - get_t _get; - set_t _set; }; /*! @@ -74,12 +75,25 @@ private: */ class usrp1e_impl : public uhd::device{ public: - typedef boost::shared_ptr sptr; - - usrp1e_impl(void); + //structors + usrp1e_impl(int node_fd); ~usrp1e_impl(void); + //the io interface + size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &); + size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &); + + /*! + * Perform an ioctl call on the device node file descriptor. + * This will throw when the internal ioctl call fails. + * \param request the control word + * \param mem pointer to some memory + */ + void ioctl(int request, void *mem); + private: + int _node_fd; + //device functions and settings void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); @@ -88,7 +102,7 @@ private: void mboard_init(void); void mboard_get(const wax::obj &, wax::obj &); void mboard_set(const wax::obj &, const wax::obj &); - wax_obj_proxy _mboard_proxy; + wax_obj_proxy::sptr _mboard_proxy; //xx dboard functions and settings void dboard_init(void); @@ -97,24 +111,24 @@ private: //rx dboard functions and settings void rx_dboard_get(const wax::obj &, wax::obj &); void rx_dboard_set(const wax::obj &, const wax::obj &); - wax_obj_proxy _rx_dboard_proxy; + wax_obj_proxy::sptr _rx_dboard_proxy; //tx dboard functions and settings void tx_dboard_get(const wax::obj &, wax::obj &); void tx_dboard_set(const wax::obj &, const wax::obj &); - wax_obj_proxy _tx_dboard_proxy; + wax_obj_proxy::sptr _tx_dboard_proxy; //rx ddc functions and settings void rx_ddc_init(void); void rx_ddc_get(const wax::obj &, wax::obj &); void rx_ddc_set(const wax::obj &, const wax::obj &); - wax_obj_proxy _rx_ddc_proxy; + wax_obj_proxy::sptr _rx_ddc_proxy; //tx duc functions and settings void tx_duc_init(void); void tx_duc_get(const wax::obj &, wax::obj &); void tx_duc_set(const wax::obj &, const wax::obj &); - wax_obj_proxy _tx_duc_proxy; + wax_obj_proxy::sptr _tx_duc_proxy; }; #endif /* INCLUDED_USRP1E_IMPL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 70420fd49..55ac0b192 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -86,8 +86,6 @@ private: */ class usrp2_impl : public uhd::device{ public: - typedef boost::shared_ptr sptr; - /*! * Create a new usrp2 impl base. * \param ctrl_transport the udp transport for control -- cgit v1.2.3 From 09a21dd6d4bc5b7f032e07cfabcba9f55d25b0f6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 22 Mar 2010 15:31:16 +0000 Subject: bit of io work --- host/lib/usrp/usrp1e/usrp1e_impl.cpp | 48 +++++++++++++++++++++++++----------- host/lib/usrp/usrp1e/usrp1e_impl.hpp | 3 ++- 2 files changed, 35 insertions(+), 16 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.cpp b/host/lib/usrp/usrp1e/usrp1e_impl.cpp index d3b0264a7..8230cc8e4 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.cpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.cpp @@ -71,21 +71,19 @@ device_addrs_t usrp1e::discover(const device_addr_t &device_addr){ * Make **********************************************************************/ device::sptr usrp1e::make(const device_addr_t &device_addr){ - std::string node = device_addr["node"]; - int node_fd = open(node.c_str(), 0); - if (node_fd < 0){ - throw std::runtime_error(str( - boost::format("Failed to open %s") % node - )); - } - return sptr(new usrp1e_impl(node_fd)); + return sptr(new usrp1e_impl(device_addr["node"])); } /*********************************************************************** * Structors **********************************************************************/ -usrp1e_impl::usrp1e_impl(int node_fd){ - _node_fd = node_fd; +usrp1e_impl::usrp1e_impl(const std::string &node){ + //open the device node and check file descriptor + if ((_node_fd = ::open(node.c_str(), O_RDWR)) < 0){ + throw std::runtime_error(str( + boost::format("Failed to open %s") % node + )); + } //initialize the mboard mboard_init(); @@ -99,7 +97,8 @@ usrp1e_impl::usrp1e_impl(int node_fd){ } usrp1e_impl::~usrp1e_impl(void){ - /* NOP */ + //close the device node file descriptor + ::close(_node_fd); } /*********************************************************************** @@ -136,11 +135,11 @@ void usrp1e_impl::get(const wax::obj &key_, wax::obj &val){ return; case DEVICE_PROP_MAX_RX_SAMPLES: - val = size_t(0); //TODO + val = size_t(_max_num_samples); return; case DEVICE_PROP_MAX_TX_SAMPLES: - val = size_t(0); //TODO + val = size_t(_max_num_samples); return; } @@ -156,5 +155,24 @@ void usrp1e_impl::set(const wax::obj &, const wax::obj &){ /*********************************************************************** * Device IO (TODO) **********************************************************************/ -size_t usrp1e_impl::send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &){return 0;} -size_t usrp1e_impl::recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &){return 0;} +size_t usrp1e_impl::send( + const boost::asio::const_buffer &, + const uhd::tx_metadata_t &, + const std::string &type +){ + if (type != "16sc"){ + throw std::runtime_error(str(boost::format("usrp1e send: cannot handle type \"%s\"") % type)); + } + return 0; +} + +size_t usrp1e_impl::recv( + const boost::asio::mutable_buffer &, + uhd::rx_metadata_t &, + const std::string &type +){ + if (type != "16sc"){ + throw std::runtime_error(str(boost::format("usrp1e recv: cannot handle type \"%s\"") % type)); + } + return 0; +} diff --git a/host/lib/usrp/usrp1e/usrp1e_impl.hpp b/host/lib/usrp/usrp1e/usrp1e_impl.hpp index 7a09254ec..c199a0465 100644 --- a/host/lib/usrp/usrp1e/usrp1e_impl.hpp +++ b/host/lib/usrp/usrp1e/usrp1e_impl.hpp @@ -76,7 +76,7 @@ private: class usrp1e_impl : public uhd::device{ public: //structors - usrp1e_impl(int node_fd); + usrp1e_impl(const std::string &node); ~usrp1e_impl(void); //the io interface @@ -92,6 +92,7 @@ public: void ioctl(int request, void *mem); private: + static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); int _node_fd; //device functions and settings -- cgit v1.2.3