From dc8bcfde805228ed5d00334ce44c6c0684dcfe2c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 25 Sep 2010 21:07:15 -0700 Subject: usb: work on libusb code to use a single context across all calls libusb allocation stuff had been moved inside of smart pointer classes to handle automatic cleanup the public device handle implementation now holds an actual libusb device inside of it needs testing - all platforms --- host/include/uhd/transport/usb_device_handle.hpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index 735a3acbe..9bb7db9c4 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -60,12 +60,6 @@ public: */ virtual boost::uint16_t get_product_id() const = 0; - /*! - * Return the device's USB address - * \return a Product ID - */ - virtual boost::uint16_t get_device_addr() const = 0; - /*! * Return a vector of USB devices on this host * \return a vector of USB device handles that match vid and pid -- cgit v1.2.3 From e4c6f42ff30aeaedf2d1eb426a221b85236fb74e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 16:53:52 -0700 Subject: usb: submit should return ssize_t, usrp1: set hash before reset after fw load --- host/include/uhd/transport/usb_control.hpp | 4 ++-- host/lib/transport/libusb1_control.cpp | 2 +- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/transport/usb_control.hpp b/host/include/uhd/transport/usb_control.hpp index 6137ecf84..f9829c3ec 100644 --- a/host/include/uhd/transport/usb_control.hpp +++ b/host/include/uhd/transport/usb_control.hpp @@ -50,9 +50,9 @@ public: * \param index 2-byte (wIndex) * \param buff buffer to hold send or receive data * \param length 2-byte (wLength) - * \return number of bytes submitted + * \return number of bytes submitted or error code */ - virtual size_t submit(boost::uint8_t request_type, + virtual ssize_t submit(boost::uint8_t request_type, boost::uint8_t request, boost::uint16_t value, boost::uint16_t index, diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp index c989a788c..f903907d0 100644 --- a/host/lib/transport/libusb1_control.cpp +++ b/host/lib/transport/libusb1_control.cpp @@ -33,7 +33,7 @@ public: _handle->claim_interface(0 /* control interface */); } - size_t submit(boost::uint8_t request_type, + ssize_t submit(boost::uint8_t request_type, boost::uint8_t request, boost::uint16_t value, boost::uint16_t index, diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 2e1bd85cd..5d73e6dd9 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -209,9 +209,9 @@ public: } //type 0x01 is end else if (type == 0x01) { + usrp_set_firmware_hash(hash); //set hash before reset usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1); - usrp_set_firmware_hash(hash); file.close(); //wait for things to settle -- cgit v1.2.3 From 543a63648f11d0e502e897f3cd98667005580c9e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 29 Sep 2010 15:35:54 -0700 Subject: usrp: transfer resize options and documentation --- host/docs/usrp1.rst | 27 ++++++ host/include/uhd/transport/usb_zero_copy.hpp | 24 +++-- host/lib/transport/libusb1_zero_copy.cpp | 140 ++++++++++++++------------- host/lib/usrp/usrp1/usrp1_impl.cpp | 26 +++-- 4 files changed, 137 insertions(+), 80 deletions(-) (limited to 'host/include') diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index 3c1431d30..7cf447719 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -95,6 +95,27 @@ Notice that the subdevice name is always specified in the 3 possible cases. B:B + +------------------------------------------------------------------------ +Change USB transfer parameters +------------------------------------------------------------------------ +The advanced user may manipulate parameters of the usb bulk transfers +for various reasons, such as lowering latency or increasing buffer size. +By default, the UHD will use values for these parameters +that are known to perform well on a variety of systems. + +The following device address can be used to manipulate USB bulk transfers: + +* **recv_xfer_size:** the size of each receive bulk transfer in bytes +* **recv_num_xfers:** the number of simultaneous receive bulk transfers +* **send_xfer_size:** the size of each send bulk transfer in bytes +* **send_num_xfers:** the number of simultaneous send bulk transfers + +Example, set the args string to the following: +:: + + serial=12345678, recv_num_xfers=16 + ------------------------------------------------------------------------ OS Specific Notes ------------------------------------------------------------------------ @@ -113,3 +134,9 @@ so that non-root users may access the device: sudo mv tmpfile /etc/udev/rules.d/10-usrp.rules sudo udevadm control --reload-rules +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Install libusb driver on Windows +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +On Windows, a driver must be installed the first time the USRP1 is attached to the host computer. +A download link for this driver can be found on the Ettus Research UHD wiki page. +Download and unpack the driver, and direct the Windows driver install wizard to the *.inf file. diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp index 75232c22a..61bf380ba 100644 --- a/host/include/uhd/transport/usb_zero_copy.hpp +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -45,16 +45,22 @@ public: * The underlying implementation may be platform specific. * * \param handle a device handle that uniquely identifying the device - * \param rx_endpoint an integer specifiying an IN endpoint number - * \param tx_endpoint an integer specifiying an OUT endpoint number - * \param buff_size total number of bytes of buffer space to allocate - * \param block_size number of bytes allocated for each I/O transaction + * \param recv_endpoint an integer specifiying an IN endpoint number + * \param send_endpoint an integer specifiying an OUT endpoint number + * \param recv_xfer_size the number of bytes for each receive transfer + * \param recv_num_xfers the number of simultaneous receive transfers + * \param send_xfer_size the number of bytes for each send transfer + * \param send_num_xfers the number of simultaneous send transfers */ - static sptr make(usb_device_handle::sptr handle, - unsigned int rx_endpoint, - unsigned int tx_endpoint, - size_t buff_size = 0, - size_t block_size = 0); + static sptr make( + usb_device_handle::sptr handle, + unsigned int recv_endpoint, + unsigned int send_endpoint, + size_t recv_xfer_size = 0, + size_t recv_num_xfers = 0, + size_t send_xfer_size = 0, + size_t send_num_xfers = 0 + ); }; }} //namespace diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index b089d11e0..f2dcff6b5 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -30,6 +30,9 @@ using namespace uhd::transport; const int libusb_timeout = 0; +static const size_t DEFAULT_NUM_XFERS = 16; //num xfers +static const size_t DEFAULT_XFER_SIZE = 32*512; //bytes + /*********************************************************************** * Helper functions ***********************************************************************/ @@ -56,7 +59,7 @@ void pp_transfer(libusb_transfer *lut) * create a bidirectional interface. It is a zero copy implementation * with respect to libusb, however, each send and recv requires a copy * operation from kernel to userspace; this is due to the usbfs - * interface provided by the kernel. + * interface provided by the kernel. **********************************************************************/ class usb_endpoint { public: @@ -107,7 +110,7 @@ private: //! a list of shared arrays for the transfer buffers std::vector > _buffers; - // Calls for processing asynchronous I/O + // Calls for processing asynchronous I/O libusb_transfer *allocate_transfer(int buff_len); void print_transfer_status(libusb_transfer *lut); }; @@ -142,7 +145,7 @@ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut){ * Constructor * Allocate libusb transfers and mark as free. For IN endpoints, * submit the transfers so that they're ready to return when - * data is available. + * data is available. */ usb_endpoint::usb_endpoint( libusb::device_handle::sptr handle, @@ -194,7 +197,7 @@ usb_endpoint::~usb_endpoint(void){ /* - * Allocate a libusb transfer + * Allocate a libusb transfer * The allocated transfer - and buffer it contains - is repeatedly * submitted, reaped, and reused and should not be freed until shutdown. * \param buff_len size of the individual buffer held by each transfer @@ -225,7 +228,7 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len){ * Asynchonous transfer submission * Submit a libusb transfer to libusb add pending status * \param lut pointer to libusb_transfer - * \return true on success or false on error + * \return true on success or false on error */ void usb_endpoint::submit(libusb_transfer *lut){ UHD_ASSERT_THROW(libusb_submit_transfer(lut) == 0); @@ -281,14 +284,14 @@ libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){ } /*********************************************************************** - * Managed buffers + * Managed buffers **********************************************************************/ /* * Libusb managed receive buffer * Construct a recv buffer from a libusb transfer. The memory held by * the libusb transfer is exposed through the managed buffer interface. * Upon destruction, the transfer and buffer are resubmitted to the - * endpoint for further use. + * endpoint for further use. */ class libusb_managed_recv_buffer_impl : public managed_recv_buffer { public: @@ -307,7 +310,7 @@ public: private: const boost::asio::const_buffer &get() const { - return _buff; + return _buff; } libusb_transfer *_lut; @@ -327,9 +330,8 @@ private: class libusb_managed_send_buffer_impl : public managed_send_buffer { public: libusb_managed_send_buffer_impl(libusb_transfer *lut, - usb_endpoint::sptr endpoint, - size_t buff_size) - : _buff(lut->buffer, buff_size), _committed(false) + usb_endpoint::sptr endpoint) + : _buff(lut->buffer, lut->length), _committed(false) { _lut = lut; _endpoint = endpoint; @@ -349,7 +351,7 @@ public: std::cerr << "UHD: send buffer already committed" << std::endl; return 0; } - + UHD_ASSERT_THROW(num_bytes <= boost::asio::buffer_size(_buff)); _lut->length = num_bytes; @@ -369,7 +371,7 @@ public: private: const boost::asio::mutable_buffer &get() const { - return _buff; + return _buff; } libusb_transfer *_lut; @@ -385,61 +387,71 @@ private: class libusb_zero_copy_impl : public usb_zero_copy { private: - usb_endpoint::sptr _rx_ep, _tx_ep; - libusb::device_handle::sptr _handle; - - size_t _recv_buff_size; - size_t _send_buff_size; - size_t _num_frames; + size_t _recv_num_frames, _send_num_frames; + usb_endpoint::sptr _recv_ep, _send_ep; public: typedef boost::shared_ptr sptr; - libusb_zero_copy_impl(libusb::device_handle::sptr handle, - unsigned int rx_endpoint, - unsigned int tx_endpoint, - size_t recv_buff_size, - size_t send_buff_size); + libusb_zero_copy_impl( + libusb::device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers + ); managed_recv_buffer::sptr get_recv_buff(void); managed_send_buffer::sptr get_send_buff(void); - size_t get_num_recv_frames(void) const { return _num_frames; } - size_t get_num_send_frames(void) const { return _num_frames; } + size_t get_num_recv_frames(void) const { return _recv_num_frames; } + size_t get_num_send_frames(void) const { return _send_num_frames; } }; /* * Constructor * Initializes libusb, opens devices, and sets up interfaces for I/O. - * Finally, creates endpoints for asynchronous I/O. + * Finally, creates endpoints for asynchronous I/O. */ -libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle, - unsigned int rx_endpoint, - unsigned int tx_endpoint, - size_t buff_size, - size_t block_size) - : _handle(handle), - _recv_buff_size(block_size), _send_buff_size(block_size), - _num_frames(buff_size / block_size) -{ - _handle->claim_interface(2 /*in interface*/); +libusb_zero_copy_impl::libusb_zero_copy_impl( + libusb::device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers +){ + _handle = handle; + + //if the sizes are left at 0 (automatic) -> use the defaults + if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE; + if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS; + if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; + if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; + + //sanity check the transfer sizes + UHD_ASSERT_THROW(recv_xfer_size % 512 == 0); + UHD_ASSERT_THROW(send_xfer_size % 512 == 0); + + //store the num xfers for the num frames count + _recv_num_frames = recv_num_xfers; + _send_num_frames = send_num_xfers; + + _handle->claim_interface(2 /*in interface*/); _handle->claim_interface(1 /*out interface*/); - _rx_ep = usb_endpoint::sptr(new usb_endpoint( + _recv_ep = usb_endpoint::sptr(new usb_endpoint( _handle, // libusb device_handle - rx_endpoint, // USB endpoint number + recv_endpoint, // USB endpoint number true, // IN endpoint - _recv_buff_size, // buffer size per transfer - _num_frames // number of libusb transfers + recv_xfer_size, // buffer size per transfer + recv_num_xfers // number of libusb transfers )); - _tx_ep = usb_endpoint::sptr(new usb_endpoint( + _send_ep = usb_endpoint::sptr(new usb_endpoint( _handle, // libusb device_handle - tx_endpoint, // USB endpoint number + send_endpoint, // USB endpoint number false, // OUT endpoint - _send_buff_size, // buffer size per transfer - _num_frames // number of libusb transfers + send_xfer_size, // buffer size per transfer + send_num_xfers // number of libusb transfers )); } @@ -447,17 +459,17 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle, * Construct a managed receive buffer from a completed libusb transfer * (happy with buffer full of data) obtained from the receive endpoint. * Return empty pointer if no transfer is available (timeout or error). - * \return pointer to a managed receive buffer + * \return pointer to a managed receive buffer */ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){ - libusb_transfer *lut = _rx_ep->get_lut_with_wait(/* TODO timeout API */); + libusb_transfer *lut = _recv_ep->get_lut_with_wait(/* TODO timeout API */); if (lut == NULL) { return managed_recv_buffer::sptr(); } else { return managed_recv_buffer::sptr( new libusb_managed_recv_buffer_impl(lut, - _rx_ep)); + _recv_ep)); } } @@ -466,38 +478,36 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){ * Construct a managed send buffer from a free libusb transfer (with * empty buffer). Return empty pointer of no transfer is available * (timeout or error). - * \return pointer to a managed send buffer + * \return pointer to a managed send buffer */ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){ - libusb_transfer *lut = _tx_ep->get_lut_with_wait(/* TODO timeout API */); + libusb_transfer *lut = _send_ep->get_lut_with_wait(/* TODO timeout API */); if (lut == NULL) { return managed_send_buffer::sptr(); } else { return managed_send_buffer::sptr( new libusb_managed_send_buffer_impl(lut, - _tx_ep, - _send_buff_size)); + _send_ep)); } } - /*********************************************************************** * USB zero_copy make functions **********************************************************************/ -usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle, - unsigned int rx_endpoint, - unsigned int tx_endpoint, - size_t buff_size, - size_t block_size) - -{ +usb_zero_copy::sptr usb_zero_copy::make( + usb_device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers +){ libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( boost::static_pointer_cast(handle)->get_device() )); - return sptr(new libusb_zero_copy_impl(dev_handle, - rx_endpoint, - tx_endpoint, - buff_size, - block_size)); + return sptr(new libusb_zero_copy_impl( + dev_handle, + recv_endpoint, send_endpoint, + recv_xfer_size, recv_num_xfers, + send_xfer_size, send_num_xfers + )); } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index b4c23bf12..793e3027d 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include using namespace uhd; @@ -107,6 +108,15 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) /*********************************************************************** * Make **********************************************************************/ +template static output_type cast_from_dev_addr( + const device_addr_t &device_addr, + const std::string &key, + output_type def_val +){ + return (device_addr.has_key(key))? + boost::lexical_cast(device_addr[key]) : def_val; +} + static device::sptr usrp1_make(const device_addr_t &device_addr) { //extract the FPGA path for the USRP1 @@ -130,11 +140,15 @@ static device::sptr usrp1_make(const device_addr_t &device_addr) usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); - data_transport = usb_zero_copy::make(handle, // identifier - 6, // IN endpoint - 2, // OUT endpoint - 2 * (1 << 20), // buffer size - 16384); // transfer size + data_transport = usb_zero_copy::make( + handle, // identifier + 6, // IN endpoint + 2, // OUT endpoint + size_t(cast_from_dev_addr(device_addr, "recv_xfer_size", 0)), + size_t(cast_from_dev_addr(device_addr, "recv_num_xfers", 0)), + size_t(cast_from_dev_addr(device_addr, "send_xfer_size", 0)), + size_t(cast_from_dev_addr(device_addr, "send_num_xfers", 0)) + ); break; } } @@ -173,7 +187,7 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, //initialize the mboard mboard_init(); - //initialize the dboards + //initialize the dboards dboard_init(); //initialize the dsps -- cgit v1.2.3 From 83596f1feb73a15a1ef8741c1c520e8cae46c2a6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 29 Sep 2010 17:43:26 -0700 Subject: usrp: added get codec rate to dboard iface --- host/include/uhd/usrp/dboard_iface.hpp | 9 +++++++++ host/lib/usrp/usrp1/dboard_iface.cpp | 5 +++++ host/lib/usrp/usrp2/dboard_iface.cpp | 4 ++++ 3 files changed, 18 insertions(+) (limited to 'host/include') diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp index c7db244f2..c430ecd3f 100644 --- a/host/include/uhd/usrp/dboard_iface.hpp +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -242,6 +242,15 @@ public: * \param enb true for enabled */ virtual void set_clock_enabled(unit_t unit, bool enb) = 0; + + /*! + * Get the rate of the codec. + * For rx, this is the rate the ADC feeds the DSP. + * For tx, this is the rate the DSP feeds the DAC. + * \param unit which unit rx or tx + * \return the codec rate in Hz + */ + virtual double get_codec_rate(unit_t unit) = 0; }; }} //namespace diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 4791b55ce..4f0549a37 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -93,6 +93,7 @@ public: std::vector get_clock_rates(unit_t); double get_clock_rate(unit_t); void set_clock_enabled(unit_t, bool); + double get_codec_rate(unit_t); private: usrp1_iface::sptr _iface; @@ -170,6 +171,10 @@ void usrp1_dboard_iface::set_clock_enabled(unit_t, bool) //TODO we can only enable for special case anyway... } +double usrp1_dboard_iface::get_codec_rate(unit_t){ + return _clock->get_master_clock_freq(); +} + /*********************************************************************** * GPIO **********************************************************************/ diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index f6d2b718a..fdfbf0d17 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -61,6 +61,7 @@ public: double get_clock_rate(unit_t); std::vector get_clock_rates(unit_t); void set_clock_enabled(unit_t, bool); + double get_codec_rate(unit_t); void write_spi( unit_t unit, @@ -158,6 +159,9 @@ void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ } } +double usrp2_dboard_iface::get_codec_rate(unit_t){ + return _clock_ctrl->get_master_clock_rate(); +} /*********************************************************************** * GPIO **********************************************************************/ -- cgit v1.2.3 From a4f8ad59b2abc6d4b1a6c65aa2652083486e3065 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 11:05:33 -0700 Subject: usrp: added subdev enabled property the dboard manager will disable all subdevs at startup and shutdown setting the subdev spec will enable only the subdevs in use all dboards are currently implemented as always enabled nothing tested --- host/include/uhd/usrp/subdev_props.hpp | 1 + host/include/uhd/usrp/subdev_spec.hpp | 6 +++++- host/lib/usrp/dboard/db_basic_and_lf.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_dbsrx.cpp | 7 +++++++ host/lib/usrp/dboard/db_rfx.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_unknown.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_wbx.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_xcvr2450.cpp | 14 ++++++++++++++ host/lib/usrp/dboard_manager.cpp | 12 +++++++++++- host/lib/usrp/misc_utils.cpp | 17 +++++++++++++++++ host/lib/usrp/subdev_spec.cpp | 4 ++++ 11 files changed, 115 insertions(+), 2 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp index cd07cb7a8..8f096ffe4 100644 --- a/host/include/uhd/usrp/subdev_props.hpp +++ b/host/include/uhd/usrp/subdev_props.hpp @@ -53,6 +53,7 @@ namespace uhd{ namespace usrp{ SUBDEV_PROP_ANTENNA_NAMES = 'A', //ro, prop_names_t SUBDEV_PROP_LO_LOCKED = 'L', //ro, bool SUBDEV_PROP_CONNECTION = 'c', //ro, subdev_conn_t + SUBDEV_PROP_ENABLED = 'e', //rw, bool SUBDEV_PROP_USE_LO_OFFSET = 'l', //ro, bool SUBDEV_PROP_RSSI = 'R', //ro, float SUBDEV_PROP_BANDWIDTH = 'B' //rw, double diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp index 2f32509b9..5de3bb3b8 100644 --- a/host/include/uhd/usrp/subdev_spec.hpp +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -19,6 +19,7 @@ #define INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP #include +#include #include #include @@ -27,7 +28,7 @@ namespace uhd{ namespace usrp{ /*! * A subdevice specification (daughterboard, subdevice) name pairing. */ - struct UHD_API subdev_spec_pair_t{ + struct UHD_API subdev_spec_pair_t : boost::equality_comparable{ //! The daughterboard name std::string db_name; @@ -45,6 +46,9 @@ namespace uhd{ namespace usrp{ ); }; + //! overloaded comparison operator for subdev_spec_pair_t + UHD_API bool operator==(const subdev_spec_pair_t &, const subdev_spec_pair_t &); + /*! * A list of (daughterboard name, subdevice name) pairs: * diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 4b0d8bf27..41f6f8002 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -149,6 +149,10 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = sd_name_to_conn[get_subdev_name()]; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -178,6 +182,9 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -241,6 +248,10 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = sd_name_to_conn[get_subdev_name()]; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -270,6 +281,9 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 81434f054..23cafea53 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -551,6 +551,10 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -587,6 +591,9 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_gain(val.as(), key.name); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + case SUBDEV_PROP_BANDWIDTH: this->set_bandwidth(val.as()); return; diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index c3ab96e59..cfc34381e 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -444,6 +444,10 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_QI; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -474,6 +478,9 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -524,6 +531,10 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = true; return; @@ -554,6 +565,9 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index f6f4f4a61..ec7ab440b 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -122,6 +122,10 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -151,6 +155,9 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -211,6 +218,10 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -240,6 +251,9 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index e473ce41e..907268aac 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -513,6 +513,10 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -543,6 +547,9 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -597,6 +604,10 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -627,6 +638,9 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 798ff74a3..0ee133f3d 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -484,6 +484,10 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -518,6 +522,9 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -572,6 +579,10 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_QI; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -602,6 +613,9 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 181f843a0..78daa1b4d 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -86,7 +86,7 @@ std::string dboard_id_t::to_pp_string(void) const{ } /*********************************************************************** - * internal helper classe + * internal helper classes **********************************************************************/ /*! * A special wax proxy object that forwards calls to a subdev. @@ -330,4 +330,14 @@ void dboard_manager_impl::set_nice_dboard_if(void){ _iface->set_pin_ctrl(unit, 0x0000); //all gpio _iface->set_clock_enabled(unit, false); //clock off } + + //disable all rx subdevices + BOOST_FOREACH(const std::string &sd_name, this->get_rx_subdev_names()){ + this->get_rx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; + } + + //disable all tx subdevices + BOOST_FOREACH(const std::string &sd_name, this->get_tx_subdev_names()){ + this->get_tx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; + } } diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 5cfcdc8d3..05308baba 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -186,6 +187,22 @@ static void verify_xx_subdev_spec( "Validate %s subdev spec failed: %s\n %s" ) % xx_type % subdev_spec.to_string() % e.what())); } + + //now use the subdev spec to enable the subdevices in use and vice-versa + BOOST_FOREACH(const std::string &db_name, mboard[dboard_names_prop].as()){ + wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)]; + BOOST_FOREACH(const std::string &sd_name, dboard[DBOARD_PROP_SUBDEV_NAMES].as()){ + try{ + bool enable = std::has(subdev_spec, subdev_spec_pair_t(db_name, sd_name)); + dboard[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)][SUBDEV_PROP_ENABLED] = enable; + } + catch(const std::exception &e){ + throw std::runtime_error(str(boost::format( + "Cannot set enabled property on subdevice %s:%s\n %s" + ) % db_name % sd_name % e.what())); + } + } + } } void usrp::verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard){ diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp index 7a3e72867..95d2cbb12 100644 --- a/host/lib/usrp/subdev_spec.cpp +++ b/host/lib/usrp/subdev_spec.cpp @@ -34,6 +34,10 @@ subdev_spec_pair_t::subdev_spec_pair_t( /* NOP */ } +bool usrp::operator==(const subdev_spec_pair_t &lhs, const subdev_spec_pair_t &rhs){ + return (lhs.db_name == rhs.db_name) and (lhs.sd_name == rhs.sd_name); +} + subdev_spec_t::subdev_spec_t(const std::string &markup){ BOOST_FOREACH(const std::string &pair, std::split_string(markup)){ if (pair == "") continue; -- cgit v1.2.3 From 2c8a7c7debf19d92065661cc1d258f97bd38e224 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 14:36:24 -0700 Subject: uhd: implemented recv timeout for zero copy interface --- host/include/uhd/transport/zero_copy.hpp | 11 +++++--- host/lib/transport/libusb1_zero_copy.cpp | 42 +++++++++++++++---------------- host/lib/transport/udp_zero_copy_asio.cpp | 5 ++-- host/lib/transport/zero_copy.cpp | 4 +-- host/lib/usrp/usrp1/io_impl.cpp | 8 +++--- host/lib/usrp/usrp2/io_impl.cpp | 5 ++-- 6 files changed, 39 insertions(+), 36 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 513291b63..8ecafd3fb 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -122,9 +122,10 @@ namespace uhd{ namespace transport{ /*! * Get a new receive buffer from this transport object. + * \param timeout_ms the timeout to get the buffer in ms * \return a managed buffer, or null sptr on timeout/error */ - virtual managed_recv_buffer::sptr get_recv_buff(void) = 0; + virtual managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms) = 0; /*! * Get the maximum number of receive frames: @@ -171,16 +172,19 @@ namespace uhd{ namespace transport{ /*! * Get a new receive buffer from this transport object. + * \param timeout_ms the timeout to get the buffer in ms + * \return a managed buffer, or null sptr on timeout/error */ - managed_recv_buffer::sptr get_recv_buff(void); + managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms); private: /*! * Perform a private copying recv. * \param buff the buffer to write data into + * \param timeout_ms the timeout to get the buffer in ms * \return the number of bytes written to buff, 0 for timeout, negative for error */ - virtual ssize_t recv(const boost::asio::mutable_buffer &buff) = 0; + virtual ssize_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms) = 0; UHD_PIMPL_DECL(impl) _impl; }; @@ -204,6 +208,7 @@ namespace uhd{ namespace transport{ /*! * Get a new send buffer from this transport object. + * \return a managed buffer, or null sptr on timeout/error */ managed_send_buffer::sptr get_send_buff(void); diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index f2dcff6b5..f9beb0b4c 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -308,8 +308,7 @@ public: } private: - const boost::asio::const_buffer &get() const - { + const boost::asio::const_buffer &get(void) const{ return _buff; } @@ -369,8 +368,7 @@ public: } private: - const boost::asio::mutable_buffer &get() const - { + const boost::asio::mutable_buffer &get(void) const{ return _buff; } @@ -395,13 +393,13 @@ public: typedef boost::shared_ptr sptr; libusb_zero_copy_impl( - libusb::device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers - ); + libusb::device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers + ); - managed_recv_buffer::sptr get_recv_buff(void); + managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms); managed_send_buffer::sptr get_send_buff(void); size_t get_num_recv_frames(void) const { return _recv_num_frames; } @@ -419,23 +417,23 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( size_t recv_xfer_size, size_t recv_num_xfers, size_t send_xfer_size, size_t send_num_xfers ){ - _handle = handle; + _handle = handle; - //if the sizes are left at 0 (automatic) -> use the defaults - if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE; - if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS; - if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; - if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; + //if the sizes are left at 0 (automatic) -> use the defaults + if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE; + if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS; + if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; + if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; //sanity check the transfer sizes UHD_ASSERT_THROW(recv_xfer_size % 512 == 0); UHD_ASSERT_THROW(send_xfer_size % 512 == 0); - //store the num xfers for the num frames count - _recv_num_frames = recv_num_xfers; - _send_num_frames = send_num_xfers; + //store the num xfers for the num frames count + _recv_num_frames = recv_num_xfers; + _send_num_frames = send_num_xfers; - _handle->claim_interface(2 /*in interface*/); + _handle->claim_interface(2 /*in interface*/); _handle->claim_interface(1 /*out interface*/); _recv_ep = usb_endpoint::sptr(new usb_endpoint( @@ -461,8 +459,8 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( * Return empty pointer if no transfer is available (timeout or error). * \return pointer to a managed receive buffer */ -managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){ - libusb_transfer *lut = _recv_ep->get_lut_with_wait(/* TODO timeout API */); +managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(size_t timeout_ms){ + libusb_transfer *lut = _recv_ep->get_lut_with_wait(timeout_ms); if (lut == NULL) { return managed_recv_buffer::sptr(); } diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index ee989ee2b..0a6c9f2af 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -35,7 +35,6 @@ static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(sizeof(boost::uint32_t) * 2 //Perhaps this is due to the kernel scheduling, //but may change with host-based flow control. static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3); -static const double RECV_TIMEOUT = 0.1; //100 ms /*********************************************************************** * Zero Copy UDP implementation with ASIO: @@ -110,11 +109,11 @@ private: boost::asio::io_service _io_service; int _sock_fd; - ssize_t recv(const boost::asio::mutable_buffer &buff){ + ssize_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms){ //setup timeval for timeout timeval tv; tv.tv_sec = 0; - tv.tv_usec = int(RECV_TIMEOUT*1e6); + tv.tv_usec = timeout_ms*1000; //setup rset for timeout fd_set rset; diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp index 8a1cde694..1fcf846a0 100644 --- a/host/lib/transport/zero_copy.cpp +++ b/host/lib/transport/zero_copy.cpp @@ -68,12 +68,12 @@ phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ /* NOP */ } -managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(void){ +managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(size_t timeout_ms){ //allocate memory boost::uint8_t *recv_mem = new boost::uint8_t[_impl->max_buff_size]; //call recv() with timeout option - ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size)); + ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size), timeout_ms); if (num_bytes <= 0) return managed_recv_buffer::sptr(); //NULL sptr diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 73974f2d6..aee760a83 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -272,18 +272,18 @@ static void usrp1_bs_vrt_unpacker( } static bool get_recv_buffs( - zero_copy_if::sptr zc_if, + zero_copy_if::sptr zc_if, size_t timeout_ms, vrt_packet_handler::managed_recv_buffs_t &buffs ){ UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = zc_if->get_recv_buff(); + buffs[0] = zc_if->get_recv_buff(timeout_ms); return buffs[0].get() != NULL; } size_t usrp1_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, size_t /*timeout_ms TODO*/ + recv_mode_t recv_mode, size_t timeout_ms ){ size_t num_samps_recvd = vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler @@ -292,7 +292,7 @@ size_t usrp1_impl::recv( io_type, _rx_otw_type, //input and output types to convert _clock_ctrl->get_master_clock_freq(), //master clock tick rate &usrp1_bs_vrt_unpacker, - boost::bind(&get_recv_buffs, _data_transport, _1), + boost::bind(&get_recv_buffs, _data_transport, timeout_ms, _1), &vrt_packet_handler::handle_overflow_nop, 0, //vrt header offset _rx_subdev_spec.size() //num channels diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 65411801d..3395f94e2 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -33,6 +33,7 @@ using namespace uhd::transport; namespace asio = boost::asio; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; +static const double RECV_TIMEOUT_MS = 100; /*********************************************************************** * io impl details (internal to this file) @@ -90,7 +91,7 @@ void usrp2_impl::io_impl::recv_pirate_loop( size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = zc_if->get_recv_buff(); + managed_recv_buffer::sptr buff = zc_if->get_recv_buff(RECV_TIMEOUT_MS); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -150,7 +151,7 @@ void usrp2_impl::io_init(void){ std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); //drain the recv buffers (may have junk) - while (data_transport->get_recv_buff().get()){}; + while (data_transport->get_recv_buff(RECV_TIMEOUT_MS).get()){}; } //the number of recv frames is the number for the first transport -- cgit v1.2.3 From b079d9d1751415139518f34d792200b041aff10b Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 30 Sep 2010 16:23:21 -0700 Subject: Made usb_device_handle UHD_API. --- host/include/uhd/transport/usb_device_handle.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/include') diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index 9bb7db9c4..6f8d868be 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -38,7 +38,7 @@ namespace uhd { namespace transport { * a true descriptor serial number string. This interface returns the * actual string descriptor. */ -class usb_device_handle : boost::noncopyable { +class UHD_API usb_device_handle : boost::noncopyable { public: typedef boost::shared_ptr sptr; -- cgit v1.2.3 From 00cd6018405b57a0982b0ce103ff858c646ee18c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 1 Oct 2010 18:22:41 -0700 Subject: uhd: implemented a double timeout (in seconds) for send and recv chains converted all size_t timeout_ms to double timeout bounded and alignment buffer now take double timeout added timeout to device::send and zero_copy_if::get_send_buff --- host/include/uhd/device.hpp | 27 ++++++++------ host/include/uhd/device.ipp | 9 +++-- host/include/uhd/transport/alignment_buffer.hpp | 9 ++--- host/include/uhd/transport/alignment_buffer.ipp | 15 +++----- host/include/uhd/transport/bounded_buffer.hpp | 12 ++---- host/include/uhd/transport/bounded_buffer.ipp | 15 ++++++-- host/include/uhd/transport/zero_copy.hpp | 18 +++++---- host/lib/transport/libusb1_zero_copy.cpp | 42 ++++++++++----------- host/lib/transport/udp_zero_copy_asio.cpp | 4 +- host/lib/transport/vrt_packet_handler.hpp | 49 +++++++++++++------------ host/lib/transport/zero_copy.cpp | 6 +-- host/lib/usrp/usrp1/io_impl.cpp | 20 +++++----- host/lib/usrp/usrp1/usrp1_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 7 ++-- host/lib/usrp/usrp2/io_impl.cpp | 32 ++++++++-------- host/lib/usrp/usrp2/usrp2_impl.hpp | 6 +-- host/test/buffer_test.cpp | 2 +- 17 files changed, 140 insertions(+), 137 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 2077cae62..992276928 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -41,9 +41,6 @@ public: typedef boost::function find_t; typedef boost::function make_t; - //! A reasonable default timeout for receive - static const size_t default_recv_timeout_ms = 100; - /*! * Register a device into the discovery and factory system. * @@ -112,12 +109,15 @@ public: * * This is a blocking call and will not return until the number * of samples returned have been read out of each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. * * \param buffs a vector of read-only memory containing IF data * \param nsamps_per_buff the number of samples to send, per buffer * \param metadata data describing the buffer's contents * \param io_type the type of data loaded in the buffer * \param send_mode tells send how to unload the buffer + * \param timeout the timeout in seconds to wait on a packet * \return the number of samples sent */ virtual size_t send( @@ -125,7 +125,8 @@ public: size_t nsamps_per_buff, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, + double timeout = 0.1 ) = 0; /*! @@ -136,7 +137,8 @@ public: size_t nsamps_per_buff, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, + double timeout = 0.1 ); /*! @@ -154,7 +156,9 @@ public: * See the rx metadata fragment flags and offset fields for details. * * This is a blocking call and will not return until the number - * of samples returned have been written into each buffer or timeout. + * of samples returned have been written into each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. * * When using the full buffer recv mode, the metadata only applies * to the first packet received and written into the recv buffers. @@ -165,7 +169,7 @@ public: * \param metadata data to fill describing the buffer * \param io_type the type of data to fill into the buffer * \param recv_mode tells recv how to load the buffer - * \param timeout_ms the timeout in milliseconds to wait for a packet + * \param timeout the timeout in seconds to wait for a packet * \return the number of samples received or 0 on error */ virtual size_t recv( @@ -174,7 +178,7 @@ public: rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, - size_t timeout_ms = default_recv_timeout_ms + double timeout = 0.1 ) = 0; /*! @@ -186,7 +190,7 @@ public: rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, - size_t timeout_ms = default_recv_timeout_ms + double timeout = 0.1 ); /*! @@ -204,12 +208,11 @@ public: /*! * Receive and asynchronous message from the device. * \param async_metadata the metadata to be filled in - * \param timeout_ms the timeout in milliseconds to wait for a message + * \param timeout the timeout in seconds to wait for a message * \return true when the async_metadata is valid, false for timeout */ virtual bool recv_async_msg( - async_metadata_t &async_metadata, - size_t timeout_ms = default_recv_timeout_ms + async_metadata_t &async_metadata, double timeout = 0.1 ) = 0; }; diff --git a/host/include/uhd/device.ipp b/host/include/uhd/device.ipp index 60a3f535d..e2e51ecd0 100644 --- a/host/include/uhd/device.ipp +++ b/host/include/uhd/device.ipp @@ -25,12 +25,13 @@ namespace uhd{ size_t nsamps_per_buff, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, + double timeout ){ return this->send( std::vector(1, buff), nsamps_per_buff, metadata, - io_type, send_mode + io_type, send_mode, timeout ); } @@ -40,12 +41,12 @@ namespace uhd{ rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, - size_t timeout_ms + double timeout ){ return this->recv( std::vector(1, buff), nsamps_per_buff, metadata, - io_type, recv_mode, timeout_ms + io_type, recv_mode, timeout ); } diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp index 29ba74efc..f44a037f8 100644 --- a/host/include/uhd/transport/alignment_buffer.hpp +++ b/host/include/uhd/transport/alignment_buffer.hpp @@ -48,20 +48,17 @@ namespace uhd{ namespace transport{ * \return true if the element fit without popping for space */ virtual bool push_with_pop_on_full( - const elem_type &elem, - const seq_type &seq, - size_t index + const elem_type &elem, const seq_type &seq, size_t index ) = 0; /*! * Pop an aligned set of elements from this alignment buffer. * \param elems a collection to store the aligned elements - * \param time the timeout time + * \param timeout the timeout in seconds * \return false when the operation times out */ virtual bool pop_elems_with_timed_wait( - std::vector &elems, - const time_duration_t &time + std::vector &elems, double timeout ) = 0; }; diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp index 61b3b60f5..5f09de0d9 100644 --- a/host/include/uhd/transport/alignment_buffer.ipp +++ b/host/include/uhd/transport/alignment_buffer.ipp @@ -41,9 +41,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ } UHD_INLINE bool push_with_pop_on_full( - const elem_type &elem, - const seq_type &seq, - size_t index + const elem_type &elem, const seq_type &seq, size_t index ){ //clear the buffer for this index if the seqs are mis-ordered if (seq < _last_seqs[index]){ @@ -54,17 +52,16 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ } UHD_INLINE bool pop_elems_with_timed_wait( - std::vector &elems, - const time_duration_t &time + std::vector &elems, double timeout ){ - boost::system_time exit_time = boost::get_system_time() + time; + boost::system_time exit_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1e6)); buff_contents_type buff_contents_tmp; std::list indexes_to_do(_all_indexes); //do an initial pop to load an initial sequence id size_t index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, exit_time - boost::get_system_time() + buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() )) return false; elems[index] = buff_contents_tmp.first; seq_type expected_seq_id = buff_contents_tmp.second; @@ -79,7 +76,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ indexes_to_do = _all_indexes; index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, exit_time - boost::get_system_time() + buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() )) return false; elems[index] = buff_contents_tmp.first; expected_seq_id = buff_contents_tmp.second; @@ -89,7 +86,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ //pop an element off for this index index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, exit_time - boost::get_system_time() + buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() )) return false; //if the sequence id matches: diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp index d1deece96..aca93b071 100644 --- a/host/include/uhd/transport/bounded_buffer.hpp +++ b/host/include/uhd/transport/bounded_buffer.hpp @@ -20,13 +20,9 @@ #include #include -#include namespace uhd{ namespace transport{ - //! typedef for the time duration type for wait operations - typedef boost::posix_time::time_duration time_duration_t; - /*! * Implement a templated bounded buffer: * Used for passing elements between threads in a producer-consumer model. @@ -64,10 +60,10 @@ namespace uhd{ namespace transport{ * Push a new element into the bounded_buffer. * Wait until the bounded_buffer becomes non-full or timeout. * \param elem the new element to push - * \param time the timeout time + * \param timeout the timeout in seconds * \return false when the operation times out */ - virtual bool push_with_timed_wait(const elem_type &elem, const time_duration_t &time) = 0; + virtual bool push_with_timed_wait(const elem_type &elem, double timeout) = 0; /*! * Pop an element from the bounded_buffer. @@ -80,10 +76,10 @@ namespace uhd{ namespace transport{ * Pop an element from the bounded_buffer. * Wait until the bounded_buffer becomes non-empty or timeout. * \param elem the element reference pop to - * \param time the timeout time + * \param timeout the timeout in seconds * \return false when the operation times out */ - virtual bool pop_with_timed_wait(elem_type &elem, const time_duration_t &time) = 0; + virtual bool pop_with_timed_wait(elem_type &elem, double timeout) = 0; /*! * Clear all elements from the bounded_buffer. diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp index e106e229e..71143741e 100644 --- a/host/include/uhd/transport/bounded_buffer.ipp +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -21,6 +21,7 @@ #include #include #include +#include namespace uhd{ namespace transport{ namespace{ /*anon*/ @@ -57,9 +58,12 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ _empty_cond.notify_one(); } - bool push_with_timed_wait(const elem_type &elem, const time_duration_t &time){ + bool push_with_timed_wait(const elem_type &elem, double timeout){ boost::unique_lock lock(_mutex); - if (not _full_cond.timed_wait(lock, time, boost::bind(&bounded_buffer_impl::not_full, this))) return false; + if (not _full_cond.timed_wait( + lock, boost::posix_time::microseconds(long(timeout*1e6)), + boost::bind(&bounded_buffer_impl::not_full, this) + )) return false; _buffer.push_front(elem); lock.unlock(); _empty_cond.notify_one(); @@ -74,9 +78,12 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ _full_cond.notify_one(); } - bool pop_with_timed_wait(elem_type &elem, const time_duration_t &time){ + bool pop_with_timed_wait(elem_type &elem, double timeout){ boost::unique_lock lock(_mutex); - if (not _empty_cond.timed_wait(lock, time, boost::bind(&bounded_buffer_impl::not_empty, this))) return false; + if (not _empty_cond.timed_wait( + lock, boost::posix_time::microseconds(long(timeout*1e6)), + boost::bind(&bounded_buffer_impl::not_empty, this) + )) return false; elem = _buffer.back(); _buffer.pop_back(); lock.unlock(); _full_cond.notify_one(); diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 8ecafd3fb..ba19b193c 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -122,10 +122,10 @@ namespace uhd{ namespace transport{ /*! * Get a new receive buffer from this transport object. - * \param timeout_ms the timeout to get the buffer in ms + * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error */ - virtual managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms) = 0; + virtual managed_recv_buffer::sptr get_recv_buff(double timeout = 0.1) = 0; /*! * Get the maximum number of receive frames: @@ -138,9 +138,10 @@ namespace uhd{ namespace transport{ /*! * Get a new send buffer from this transport object. + * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error */ - virtual managed_send_buffer::sptr get_send_buff(void) = 0; + virtual managed_send_buffer::sptr get_send_buff(double timeout = 0.1) = 0; /*! * Get the maximum number of send frames: @@ -172,19 +173,19 @@ namespace uhd{ namespace transport{ /*! * Get a new receive buffer from this transport object. - * \param timeout_ms the timeout to get the buffer in ms + * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error */ - managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms); + managed_recv_buffer::sptr get_recv_buff(double timeout); private: /*! * Perform a private copying recv. * \param buff the buffer to write data into - * \param timeout_ms the timeout to get the buffer in ms + * \param timeout the timeout to get the buffer in seconds * \return the number of bytes written to buff, 0 for timeout, negative for error */ - virtual ssize_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms) = 0; + virtual ssize_t recv(const boost::asio::mutable_buffer &buff, double timeout) = 0; UHD_PIMPL_DECL(impl) _impl; }; @@ -208,9 +209,10 @@ namespace uhd{ namespace transport{ /*! * Get a new send buffer from this transport object. + * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error */ - managed_send_buffer::sptr get_send_buff(void); + managed_send_buffer::sptr get_send_buff(double timeout); private: /*! diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index f9beb0b4c..7f2bc3468 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -24,12 +24,10 @@ #include #include #include -#include using namespace uhd::transport; -const int libusb_timeout = 0; - +static const double CLEANUP_TIMEOUT = 0.2; //seconds static const size_t DEFAULT_NUM_XFERS = 16; //num xfers static const size_t DEFAULT_XFER_SIZE = 32*512; //bytes @@ -84,10 +82,10 @@ public: * Get an available transfer: * For inputs, this is a just filled transfer. * For outputs, this is a just emptied transfer. - * \param timeout_ms the timeout to wait for a lut + * \param timeout the timeout to wait for a lut * \return the transfer pointer or NULL if timeout */ - libusb_transfer *get_lut_with_wait(size_t timeout_ms = 100); + libusb_transfer *get_lut_with_wait(double timeout); //Callback use only void callback_handle_transfer(libusb_transfer *lut); @@ -187,7 +185,7 @@ usb_endpoint::~usb_endpoint(void){ } //collect canceled transfers (drain the queue) - while (this->get_lut_with_wait() != NULL){}; + while (this->get_lut_with_wait(CLEANUP_TIMEOUT) != NULL){}; //free all transfers BOOST_FOREACH(libusb_transfer *lut, _all_luts){ @@ -274,12 +272,10 @@ void usb_endpoint::print_transfer_status(libusb_transfer *lut){ } } -libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){ +libusb_transfer *usb_endpoint::get_lut_with_wait(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw libusb_transfer *lut; - if (_completed_list->pop_with_timed_wait( - lut, boost::posix_time::milliseconds(timeout_ms) - )) return lut; + if (_completed_list->pop_with_timed_wait(lut, timeout)) return lut; return NULL; } @@ -399,8 +395,8 @@ public: size_t send_xfer_size, size_t send_num_xfers ); - managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms); - managed_send_buffer::sptr get_send_buff(void); + managed_recv_buffer::sptr get_recv_buff(double); + managed_send_buffer::sptr get_send_buff(double); size_t get_num_recv_frames(void) const { return _recv_num_frames; } size_t get_num_send_frames(void) const { return _send_num_frames; } @@ -459,8 +455,8 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( * Return empty pointer if no transfer is available (timeout or error). * \return pointer to a managed receive buffer */ -managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(size_t timeout_ms){ - libusb_transfer *lut = _recv_ep->get_lut_with_wait(timeout_ms); +managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(double timeout){ + libusb_transfer *lut = _recv_ep->get_lut_with_wait(timeout); if (lut == NULL) { return managed_recv_buffer::sptr(); } @@ -478,8 +474,8 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(size_t timeout_ms * (timeout or error). * \return pointer to a managed send buffer */ -managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){ - libusb_transfer *lut = _send_ep->get_lut_with_wait(/* TODO timeout API */); +managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ + libusb_transfer *lut = _send_ep->get_lut_with_wait(timeout); if (lut == NULL) { return managed_send_buffer::sptr(); } @@ -494,18 +490,18 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){ * USB zero_copy make functions **********************************************************************/ usb_zero_copy::sptr usb_zero_copy::make( - usb_device_handle::sptr handle, + usb_device_handle::sptr handle, unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers ){ libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( boost::static_pointer_cast(handle)->get_device() )); return sptr(new libusb_zero_copy_impl( - dev_handle, - recv_endpoint, send_endpoint, - recv_xfer_size, recv_num_xfers, - send_xfer_size, send_num_xfers + dev_handle, + recv_endpoint, send_endpoint, + recv_xfer_size, recv_num_xfers, + send_xfer_size, send_num_xfers )); } diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 0a6c9f2af..3130830a5 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -109,11 +109,11 @@ private: boost::asio::io_service _io_service; int _sock_fd; - ssize_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms){ + ssize_t recv(const boost::asio::mutable_buffer &buff, double timeout){ //setup timeval for timeout timeval tv; tv.tv_sec = 0; - tv.tv_usec = timeout_ms*1000; + tv.tv_usec = long(timeout*1e6); //setup rset for timeout fd_set rset; diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index b603f1371..e11afff30 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -303,18 +303,18 @@ template UHD_INLINE T get_context_code( * Pack a vrt header, copy-convert the data, and send it. * - helper function for vrt_packet_handler::send ******************************************************************/ - static UHD_INLINE void _send1( + static UHD_INLINE size_t _send1( send_state &state, const std::vector &buffs, - size_t offset_bytes, - size_t num_samps, + const size_t offset_bytes, + const size_t num_samps, uhd::transport::vrt::if_packet_info_t &if_packet_info, const uhd::io_type_t &io_type, const uhd::otw_type_t &otw_type, const vrt_packer_t &vrt_packer, const get_send_buffs_t &get_send_buffs, - size_t vrt_header_offset_words32, - size_t chans_per_otw_buff + const size_t vrt_header_offset_words32, + const size_t chans_per_otw_buff ){ //load the rest of the if_packet_info in here if_packet_info.num_payload_words32 = (num_samps*chans_per_otw_buff*otw_type.get_sample_size())/sizeof(boost::uint32_t); @@ -322,7 +322,7 @@ template UHD_INLINE T get_context_code( //get send buffers for each channel managed_send_buffs_t send_buffs(buffs.size()/chans_per_otw_buff); - UHD_ASSERT_THROW(get_send_buffs(send_buffs)); + if (not get_send_buffs(send_buffs)) return 0; std::vector io_buffs(chans_per_otw_buff); for (size_t i = 0; i < buffs.size(); i+=chans_per_otw_buff){ @@ -347,6 +347,7 @@ template UHD_INLINE T get_context_code( std::cerr << "commit to send buffer returned less than commit size" << std::endl; } } + return num_samps; } /******************************************************************* @@ -381,7 +382,6 @@ template UHD_INLINE T get_context_code( //////////////////////////////////////////////////////////////// case uhd::device::SEND_MODE_ONE_PACKET:{ //////////////////////////////////////////////////////////////// - size_t num_samps = std::min(total_num_samps, max_samples_per_packet); //fill in parts of the packet info overwrote in full buff mode if_packet_info.has_tsi = metadata.has_time_spec; @@ -389,10 +389,10 @@ template UHD_INLINE T get_context_code( if_packet_info.sob = metadata.start_of_burst; if_packet_info.eob = metadata.end_of_burst; - _send1( + return _send1( state, buffs, 0, - num_samps, + std::min(total_num_samps, max_samples_per_packet), if_packet_info, io_type, otw_type, vrt_packer, @@ -400,31 +400,32 @@ template UHD_INLINE T get_context_code( vrt_header_offset_words32, chans_per_otw_buff ); - return num_samps; } //////////////////////////////////////////////////////////////// case uhd::device::SEND_MODE_FULL_BUFF:{ //////////////////////////////////////////////////////////////// - //calculate constants for fragmentation - const size_t num_fragments = (total_num_samps+max_samples_per_packet-1)/max_samples_per_packet; - static const size_t first_fragment_index = 0; - const size_t final_fragment_index = num_fragments-1; + size_t total_num_samps_sent = 0; //loop through the following fragment indexes - for (size_t n = first_fragment_index; n <= final_fragment_index; n++){ + while(total_num_samps_sent < total_num_samps){ + + //calculate per-loop-iteration variables + const size_t total_num_samps_unsent = total_num_samps - total_num_samps_sent; + const bool first_fragment = (total_num_samps_sent == 0); + const bool final_fragment = (total_num_samps_unsent <= max_samples_per_packet); //calculate new flags for the fragments - if_packet_info.has_tsi = metadata.has_time_spec and (n == first_fragment_index); - if_packet_info.has_tsf = metadata.has_time_spec and (n == first_fragment_index); - if_packet_info.sob = metadata.start_of_burst and (n == first_fragment_index); - if_packet_info.eob = metadata.end_of_burst and (n == final_fragment_index); + if_packet_info.has_tsi = metadata.has_time_spec and first_fragment; + if_packet_info.has_tsf = if_packet_info.has_tsi; + if_packet_info.sob = metadata.start_of_burst and first_fragment; + if_packet_info.eob = metadata.end_of_burst and final_fragment; //send the fragment with the helper function - _send1( + const size_t num_samps_sent = _send1( state, - buffs, n*max_samples_per_packet*io_type.size, - (n == final_fragment_index)?(total_num_samps%max_samples_per_packet):max_samples_per_packet, + buffs, total_num_samps_sent*io_type.size, + std::min(total_num_samps_unsent, max_samples_per_packet), if_packet_info, io_type, otw_type, vrt_packer, @@ -432,8 +433,10 @@ template UHD_INLINE T get_context_code( vrt_header_offset_words32, chans_per_otw_buff ); + total_num_samps_sent += num_samps_sent; + if (num_samps_sent == 0) return total_num_samps_sent; } - return total_num_samps; + return total_num_samps_sent; } default: throw std::runtime_error("unknown send mode"); diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp index 1fcf846a0..dfb65951f 100644 --- a/host/lib/transport/zero_copy.cpp +++ b/host/lib/transport/zero_copy.cpp @@ -68,12 +68,12 @@ phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ /* NOP */ } -managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(size_t timeout_ms){ +managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(double timeout){ //allocate memory boost::uint8_t *recv_mem = new boost::uint8_t[_impl->max_buff_size]; //call recv() with timeout option - ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size), timeout_ms); + ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size), timeout); if (num_bytes <= 0) return managed_recv_buffer::sptr(); //NULL sptr @@ -138,6 +138,6 @@ phony_zero_copy_send_if::~phony_zero_copy_send_if(void){ delete [] _impl->send_mem; } -managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(void){ +managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(double){ return _impl->send_buff; //FIXME there is only ever one send buff, we assume that the caller doesnt hang onto these } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index aee760a83..8d9c68961 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -94,12 +94,13 @@ struct usrp1_impl::io_impl{ //all of this to ensure only full buffers are committed managed_send_buffer::sptr send_buff; size_t num_bytes_committed; + double send_timeout; boost::uint8_t pseudo_buff[BYTES_PER_PACKET]; ssize_t phony_commit_pseudo_buff(size_t num_bytes); ssize_t phony_commit_send_buff(size_t num_bytes); ssize_t commit_send_buff(void); void flush_send_buff(void); - bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &); + bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &, double); //helpers to get at the send buffer + offset inline void *get_send_mem_ptr(void){ @@ -159,14 +160,15 @@ void usrp1_impl::io_impl::flush_send_buff(void){ */ ssize_t usrp1_impl::io_impl::commit_send_buff(void){ ssize_t ret = send_buff->commit(num_bytes_committed); - send_buff = data_transport->get_send_buff(); + send_buff = data_transport->get_send_buff(send_timeout); num_bytes_committed = 0; return ret; } bool usrp1_impl::io_impl::get_send_buffs( - vrt_packet_handler::managed_send_buffs_t &buffs + vrt_packet_handler::managed_send_buffs_t &buffs, double timeout ){ + send_timeout = timeout; UHD_ASSERT_THROW(buffs.size() == 1); //not enough bytes free -> use the pseudo buffer @@ -216,7 +218,7 @@ static void usrp1_bs_vrt_packer( size_t usrp1_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, double timeout ){ size_t num_samps_sent = vrt_packet_handler::send( _io_impl->packet_handler_send_state, //last state of the send handler @@ -225,7 +227,7 @@ size_t usrp1_impl::send( io_type, _tx_otw_type, //input and output types to convert _clock_ctrl->get_master_clock_freq(), //master clock tick rate &usrp1_bs_vrt_packer, - boost::bind(&usrp1_impl::io_impl::get_send_buffs, _io_impl.get(), _1), + boost::bind(&usrp1_impl::io_impl::get_send_buffs, _io_impl.get(), _1, timeout), get_max_send_samps_per_packet(), 0, //vrt header offset _tx_subdev_spec.size() //num channels @@ -272,18 +274,18 @@ static void usrp1_bs_vrt_unpacker( } static bool get_recv_buffs( - zero_copy_if::sptr zc_if, size_t timeout_ms, + zero_copy_if::sptr zc_if, double timeout, vrt_packet_handler::managed_recv_buffs_t &buffs ){ UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = zc_if->get_recv_buff(timeout_ms); + buffs[0] = zc_if->get_recv_buff(timeout); return buffs[0].get() != NULL; } size_t usrp1_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, size_t timeout_ms + recv_mode_t recv_mode, double timeout ){ size_t num_samps_recvd = vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler @@ -292,7 +294,7 @@ size_t usrp1_impl::recv( io_type, _rx_otw_type, //input and output types to convert _clock_ctrl->get_master_clock_freq(), //master clock tick rate &usrp1_bs_vrt_unpacker, - boost::bind(&get_recv_buffs, _data_transport, timeout_ms, _1), + boost::bind(&get_recv_buffs, _data_transport, timeout, _1), &vrt_packet_handler::handle_overflow_nop, 0, //vrt header offset _rx_subdev_spec.size() //num channels diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 156fc119f..6ebd6bb09 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -209,9 +209,9 @@ usrp1_impl::~usrp1_impl(void){ /* NOP */ } -bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, size_t timeout_ms){ +bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, double timeout){ //dummy fill-in for the recv_async_msg - boost::this_thread::sleep(boost::posix_time::milliseconds(timeout_ms)); + boost::this_thread::sleep(boost::posix_time::microseconds(long(timeout*1e6))); return false; } diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 20ae3c02a..f2c464610 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -83,13 +83,12 @@ public: size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, - send_mode_t); + send_mode_t, double); size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, - recv_mode_t, - size_t timeout); + recv_mode_t, double); static const size_t BYTES_PER_PACKET = 512*4; //under the transfer size @@ -101,7 +100,7 @@ public: return BYTES_PER_PACKET/_rx_otw_type.get_sample_size()/_rx_subdev_spec.size(); } - bool recv_async_msg(uhd::async_metadata_t &, size_t); + bool recv_async_msg(uhd::async_metadata_t &, double); private: /*! diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 3395f94e2..c0d8ab029 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -33,7 +33,6 @@ using namespace uhd::transport; namespace asio = boost::asio; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; -static const double RECV_TIMEOUT_MS = 100; /*********************************************************************** * io impl details (internal to this file) @@ -59,9 +58,9 @@ struct usrp2_impl::io_impl{ recv_pirate_crew.join_all(); } - bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, size_t timeout_ms){ + bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw - return recv_pirate_booty->pop_elems_with_timed_wait(buffs, boost::posix_time::milliseconds(timeout_ms)); + return recv_pirate_booty->pop_elems_with_timed_wait(buffs, timeout); } //state management for the vrt packet handler code @@ -91,7 +90,7 @@ void usrp2_impl::io_impl::recv_pirate_loop( size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = zc_if->get_recv_buff(RECV_TIMEOUT_MS); + managed_recv_buffer::sptr buff = zc_if->get_recv_buff(); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -151,7 +150,7 @@ void usrp2_impl::io_init(void){ std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); //drain the recv buffers (may have junk) - while (data_transport->get_recv_buff(RECV_TIMEOUT_MS).get()){}; + while (data_transport->get_recv_buff().get()){}; } //the number of recv frames is the number for the first transport @@ -179,12 +178,10 @@ void usrp2_impl::io_init(void){ * Async Data **********************************************************************/ bool usrp2_impl::recv_async_msg( - async_metadata_t &async_metadata, size_t timeout_ms + async_metadata_t &async_metadata, double timeout ){ boost::this_thread::disable_interruption di; //disable because the wait can throw - return _io_impl->async_msg_fifo->pop_with_timed_wait( - async_metadata, boost::posix_time::milliseconds(timeout_ms) - ); + return _io_impl->async_msg_fifo->pop_with_timed_wait(async_metadata, timeout); } /*********************************************************************** @@ -192,19 +189,22 @@ bool usrp2_impl::recv_async_msg( **********************************************************************/ static bool get_send_buffs( const std::vector &trans, - vrt_packet_handler::managed_send_buffs_t &buffs + vrt_packet_handler::managed_send_buffs_t &buffs, + double timeout ){ UHD_ASSERT_THROW(trans.size() == buffs.size()); + bool good = true; for (size_t i = 0; i < buffs.size(); i++){ - buffs[i] = trans[i]->get_send_buff(); + buffs[i] = trans[i]->get_send_buff(timeout); + good = good and (buffs[i].get() != NULL); } - return true; + return good; } size_t usrp2_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, double timeout ){ return vrt_packet_handler::send( _io_impl->packet_handler_send_state, //last state of the send handler @@ -213,7 +213,7 @@ size_t usrp2_impl::send( io_type, _io_helper.get_tx_otw_type(), //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_pack_be, - boost::bind(&get_send_buffs, _data_transports, _1), + boost::bind(&get_send_buffs, _data_transports, _1, timeout), get_max_send_samps_per_packet() ); } @@ -224,7 +224,7 @@ size_t usrp2_impl::send( size_t usrp2_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, size_t timeout_ms + recv_mode_t recv_mode, double timeout ){ return vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler @@ -233,6 +233,6 @@ size_t usrp2_impl::recv( io_type, _io_helper.get_rx_otw_type(), //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_be, - boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout_ms) + boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout) ); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 157d17057..e8763b284 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -234,7 +234,7 @@ public: size_t send( const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, - uhd::device::send_mode_t + uhd::device::send_mode_t, double ); size_t get_max_recv_samps_per_packet(void) const{ return _io_helper.get_max_recv_samps_per_packet(); @@ -242,9 +242,9 @@ public: size_t recv( const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, - uhd::device::recv_mode_t, size_t + uhd::device::recv_mode_t, double ); - bool recv_async_msg(uhd::async_metadata_t &, size_t); + bool recv_async_msg(uhd::async_metadata_t &, double); private: //device properties interface diff --git a/host/test/buffer_test.cpp b/host/test/buffer_test.cpp index aadb3f951..8445412e7 100644 --- a/host/test/buffer_test.cpp +++ b/host/test/buffer_test.cpp @@ -23,7 +23,7 @@ using namespace boost::assign; using namespace uhd::transport; -static const boost::posix_time::milliseconds timeout(10); +static const double timeout = 0.01/*secs*/; BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_timed_wait){ bounded_buffer::sptr bb(bounded_buffer::make(3)); -- cgit v1.2.3 From 7352c95037fa57d37dd7adc4c2ea6935006b56c8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 2 Oct 2010 23:15:46 -0700 Subject: uhd: reworked the zero copy interface - recv buffers have a release call - safe make function for recv buffers (buff + release callback) - send buffer commits now have a void return - safe make function for send buffers (buff + commit callback) The reason for the void return from commit is that ssize_t num_bytes was never returning anything of use. That is for all of the zero copy implementations so far, commit cannot really error (being asynchronous). libusb zero copy impl was reworked to support the new interface. USRP1 io_impl with the psuedo managed buffer was replaced with safe_make. Also, usrp1 io_impl was simplified greatly due to commit returning void now. UDP zero copy asio was disabled (in this commit, until its reworked). Phony send and recv interfaces were removed completely. --- host/include/uhd/transport/zero_copy.hpp | 112 +++++++--------------- host/lib/transport/CMakeLists.txt | 4 +- host/lib/transport/libusb1_zero_copy.cpp | 149 +++++++----------------------- host/lib/transport/vrt_packet_handler.hpp | 4 +- host/lib/transport/zero_copy.cpp | 121 +++++++++--------------- host/lib/usrp/usrp1/io_impl.cpp | 65 ++++--------- 6 files changed, 130 insertions(+), 325 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index ba19b193c..9dd16280c 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -19,10 +19,10 @@ #define INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP #include -#include #include #include #include +#include namespace uhd{ namespace transport{ @@ -34,14 +34,27 @@ namespace uhd{ namespace transport{ class UHD_API managed_recv_buffer : boost::noncopyable{ public: typedef boost::shared_ptr sptr; + typedef boost::function release_fcn_t; + + /*! + * Make a safe managed receive buffer: + * A safe managed buffer ensures that release is called once, + * either by the user or automatically upon deconstruction. + * \param buff a reference to the constant buffer + * \param release_fcn callback to release the memory + * \return a new managed receive buffer + */ + static sptr make_safe( + const boost::asio::const_buffer &buff, + const release_fcn_t &release_fcn + ); /*! - * Managed recv buffer destructor: * Signal to the transport that we are done with the buffer. - * This should be called to release the buffer to the transport. + * This should be called to release the buffer to the transport object. * After calling, the referenced memory should be considered invalid. */ - virtual ~managed_recv_buffer(void) = 0; + virtual void release(void) = 0; /*! * Get the size of the underlying buffer. @@ -71,20 +84,34 @@ namespace uhd{ namespace transport{ /*! * A managed send buffer: * Contains a reference to transport-managed memory, - * and a method to release the memory after writing. + * and a method to commit the memory after writing. */ class UHD_API managed_send_buffer : boost::noncopyable{ public: typedef boost::shared_ptr sptr; + typedef boost::function commit_fcn_t; + + /*! + * Make a safe managed send buffer: + * A safe managed buffer ensures that commit is called once, + * either by the user or automatically upon deconstruction. + * In the later case, the deconstructor will call commit(0). + * \param buff a reference to the mutable buffer + * \param commit_fcn callback to commit the memory + * \return a new managed send buffer + */ + static sptr make_safe( + const boost::asio::mutable_buffer &buff, + const commit_fcn_t &commit_fcn + ); /*! * Signal to the transport that we are done with the buffer. * This should be called to commit the write to the transport object. * After calling, the referenced memory should be considered invalid. * \param num_bytes the number of bytes written into the buffer - * \return the number of bytes written, 0 for timeout, negative for error */ - virtual ssize_t commit(size_t num_bytes) = 0; + virtual void commit(size_t num_bytes) = 0; /*! * Get the size of the underlying buffer. @@ -154,77 +181,6 @@ namespace uhd{ namespace transport{ }; - /*! - * A phony-zero-copy interface for transport objects that - * provides a zero-copy interface on top of copying transport. - * This interface implements the get managed recv buffer, - * the base class must implement the private recv method. - */ - class UHD_API phony_zero_copy_recv_if : public virtual zero_copy_if{ - public: - /*! - * Create a phony zero copy recv interface. - * \param max_buff_size max buffer size in bytes - */ - phony_zero_copy_recv_if(size_t max_buff_size); - - //! destructor - virtual ~phony_zero_copy_recv_if(void); - - /*! - * Get a new receive buffer from this transport object. - * \param timeout the timeout to get the buffer in seconds - * \return a managed buffer, or null sptr on timeout/error - */ - managed_recv_buffer::sptr get_recv_buff(double timeout); - - private: - /*! - * Perform a private copying recv. - * \param buff the buffer to write data into - * \param timeout the timeout to get the buffer in seconds - * \return the number of bytes written to buff, 0 for timeout, negative for error - */ - virtual ssize_t recv(const boost::asio::mutable_buffer &buff, double timeout) = 0; - - UHD_PIMPL_DECL(impl) _impl; - }; - - /*! - * A phony-zero-copy interface for transport objects that - * provides a zero-copy interface on top of copying transport. - * This interface implements the get managed send buffer, - * the base class must implement the private send method. - */ - class UHD_API phony_zero_copy_send_if : public virtual zero_copy_if{ - public: - /*! - * Create a phony zero copy send interface. - * \param max_buff_size max buffer size in bytes - */ - phony_zero_copy_send_if(size_t max_buff_size); - - //! destructor - virtual ~phony_zero_copy_send_if(void); - - /*! - * Get a new send buffer from this transport object. - * \param timeout the timeout to get the buffer in seconds - * \return a managed buffer, or null sptr on timeout/error - */ - managed_send_buffer::sptr get_send_buff(double timeout); - - private: - /*! - * Perform a private copying send. - * \param buff the buffer to read data from - * \return the number of bytes read from buff, 0 for timeout, negative for error - */ - virtual ssize_t send(const boost::asio::const_buffer &buff) = 0; - - UHD_PIMPL_DECL(impl) _impl; - }; - }} //namespace #endif /* INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP */ diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 61616d077..2be2c89ec 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -36,6 +36,8 @@ IF(LIBUSB_FOUND) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/msvc) ENDIF(MSVC) SET(HAVE_USB_SUPPORT TRUE) +ELSE(LIBUSB_FOUND) + #TODO dummy usb ENDIF(LIBUSB_FOUND) IF(HAVE_USB_SUPPORT) @@ -99,7 +101,7 @@ SET_SOURCE_FILES_PROPERTIES( LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/transport/if_addrs.cpp ${CMAKE_SOURCE_DIR}/lib/transport/udp_simple.cpp - ${CMAKE_SOURCE_DIR}/lib/transport/udp_zero_copy_asio.cpp + #${CMAKE_SOURCE_DIR}/lib/transport/udp_zero_copy_asio.cpp ${CMAKE_SOURCE_DIR}/lib/transport/vrt_packet_handler.hpp ${CMAKE_SOURCE_DIR}/lib/transport/zero_copy.cpp ) diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 7f2bc3468..e1cc8398c 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -95,9 +95,6 @@ private: int _endpoint; bool _input; - size_t _transfer_size; - size_t _num_transfers; - //! hold a bounded buffer of completed transfers typedef bounded_buffer lut_buff_type; lut_buff_type::sptr _completed_list; @@ -154,14 +151,12 @@ usb_endpoint::usb_endpoint( ): _handle(handle), _endpoint(endpoint), - _input(input), - _transfer_size(transfer_size), - _num_transfers(num_transfers) + _input(input) { _completed_list = lut_buff_type::make(num_transfers); - for (size_t i = 0; i < _num_transfers; i++){ - _all_luts.push_back(allocate_transfer(_transfer_size)); + for (size_t i = 0; i < num_transfers; i++){ + _all_luts.push_back(allocate_transfer(transfer_size)); //input luts are immediately submitted to be filled //output luts go into the completed list as free buffers @@ -280,126 +275,44 @@ libusb_transfer *usb_endpoint::get_lut_with_wait(double timeout){ } /*********************************************************************** - * Managed buffers + * USB zero_copy device class **********************************************************************/ -/* - * Libusb managed receive buffer - * Construct a recv buffer from a libusb transfer. The memory held by - * the libusb transfer is exposed through the managed buffer interface. - * Upon destruction, the transfer and buffer are resubmitted to the - * endpoint for further use. - */ -class libusb_managed_recv_buffer_impl : public managed_recv_buffer { +class libusb_zero_copy_impl : public usb_zero_copy { public: - libusb_managed_recv_buffer_impl(libusb_transfer *lut, - usb_endpoint::sptr endpoint) - : _buff(lut->buffer, lut->length) - { - _lut = lut; - _endpoint = endpoint; - } - - ~libusb_managed_recv_buffer_impl(void){ - _endpoint->submit(_lut); - } + typedef boost::shared_ptr sptr; -private: - const boost::asio::const_buffer &get(void) const{ - return _buff; - } + libusb_zero_copy_impl( + libusb::device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers + ); - libusb_transfer *_lut; - usb_endpoint::sptr _endpoint; - const boost::asio::const_buffer _buff; -}; + managed_recv_buffer::sptr get_recv_buff(double); + managed_send_buffer::sptr get_send_buff(double); -/* - * Libusb managed send buffer - * Construct a send buffer from a libusb transfer. The memory held by - * the libusb transfer is exposed through the managed buffer interface. - * Committing the buffer will set the data length and submit the buffer - * to the endpoint. Submitting a buffer multiple times or destroying - * the buffer before committing is an error. For the latter, the transfer - * is returned to the endpoint with no data for reuse. - */ -class libusb_managed_send_buffer_impl : public managed_send_buffer { -public: - libusb_managed_send_buffer_impl(libusb_transfer *lut, - usb_endpoint::sptr endpoint) - : _buff(lut->buffer, lut->length), _committed(false) - { - _lut = lut; - _endpoint = endpoint; - } + size_t get_num_recv_frames(void) const { return _recv_num_frames; } + size_t get_num_send_frames(void) const { return _send_num_frames; } - ~libusb_managed_send_buffer_impl(void){ - if (!_committed) { - _lut->length = 0; - _lut->actual_length = 0; - _endpoint->submit(_lut); - } +private: + void release(libusb_transfer *lut){ + _recv_ep->submit(lut); } - ssize_t commit(size_t num_bytes) - { - if (_committed) { - std::cerr << "UHD: send buffer already committed" << std::endl; - return 0; - } - - UHD_ASSERT_THROW(num_bytes <= boost::asio::buffer_size(_buff)); - - _lut->length = num_bytes; - _lut->actual_length = 0; - + void commit(libusb_transfer *lut, size_t num_bytes){ + lut->length = num_bytes; try{ - _endpoint->submit(_lut); - _committed = true; - return num_bytes; + _send_ep->submit(lut); } catch(const std::exception &e){ std::cerr << "Error in commit: " << e.what() << std::endl; - return -1; } } -private: - const boost::asio::mutable_buffer &get(void) const{ - return _buff; - } - - libusb_transfer *_lut; - usb_endpoint::sptr _endpoint; - const boost::asio::mutable_buffer _buff; - bool _committed; -}; - - -/*********************************************************************** - * USB zero_copy device class - **********************************************************************/ -class libusb_zero_copy_impl : public usb_zero_copy -{ -private: libusb::device_handle::sptr _handle; + size_t _recv_xfer_size, _send_xfer_size; size_t _recv_num_frames, _send_num_frames; usb_endpoint::sptr _recv_ep, _send_ep; - -public: - typedef boost::shared_ptr sptr; - - libusb_zero_copy_impl( - libusb::device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers - ); - - managed_recv_buffer::sptr get_recv_buff(double); - managed_send_buffer::sptr get_send_buff(double); - - size_t get_num_recv_frames(void) const { return _recv_num_frames; } - size_t get_num_send_frames(void) const { return _send_num_frames; } }; /* @@ -426,7 +339,9 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( UHD_ASSERT_THROW(send_xfer_size % 512 == 0); //store the num xfers for the num frames count + _recv_xfer_size = recv_xfer_size; _recv_num_frames = recv_num_xfers; + _send_xfer_size = send_xfer_size; _send_num_frames = send_num_xfers; _handle->claim_interface(2 /*in interface*/); @@ -461,9 +376,10 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(double timeout){ return managed_recv_buffer::sptr(); } else { - return managed_recv_buffer::sptr( - new libusb_managed_recv_buffer_impl(lut, - _recv_ep)); + return managed_recv_buffer::make_safe( + boost::asio::const_buffer(lut->buffer, lut->actual_length), + boost::bind(&libusb_zero_copy_impl::release, this, lut) + ); } } @@ -480,9 +396,10 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ return managed_send_buffer::sptr(); } else { - return managed_send_buffer::sptr( - new libusb_managed_send_buffer_impl(lut, - _send_ep)); + return managed_send_buffer::make_safe( + boost::asio::mutable_buffer(lut->buffer, _send_xfer_size), + boost::bind(&libusb_zero_copy_impl::commit, this, lut, _1) + ); } } diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index e11afff30..939517411 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -343,9 +343,7 @@ template UHD_INLINE T get_context_code( //commit the samples to the zero-copy interface size_t num_bytes_total = (vrt_header_offset_words32+if_packet_info.num_packet_words32)*sizeof(boost::uint32_t); - if (send_buffs[i]->commit(num_bytes_total) < ssize_t(num_bytes_total)){ - std::cerr << "commit to send buffer returned less than commit size" << std::endl; - } + send_buffs[i]->commit(num_bytes_total); } return num_samps; } diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp index dfb65951f..a5a864a04 100644 --- a/host/lib/transport/zero_copy.cpp +++ b/host/lib/transport/zero_copy.cpp @@ -16,32 +16,35 @@ // #include -#include -#include -#include using namespace uhd::transport; /*********************************************************************** - * The pure-virtual deconstructor needs an implementation to be happy + * Safe managed receive buffer **********************************************************************/ -managed_recv_buffer::~managed_recv_buffer(void){ +static void release_nop(void){ /* NOP */ } -/*********************************************************************** - * Phony zero-copy recv interface implementation - **********************************************************************/ - -//! phony zero-copy recv buffer implementation -class managed_recv_buffer_impl : public managed_recv_buffer{ +class safe_managed_receive_buffer : public managed_recv_buffer{ public: - managed_recv_buffer_impl(const boost::asio::const_buffer &buff) : _buff(buff){ + safe_managed_receive_buffer( + const boost::asio::const_buffer &buff, + const release_fcn_t &release_fcn + ): + _buff(buff), _release_fcn(release_fcn) + { /* NOP */ } - ~managed_recv_buffer_impl(void){ - delete [] this->cast(); + ~safe_managed_receive_buffer(void){ + _release_fcn(); + } + + void release(void){ + release_fcn_t release_fcn = _release_fcn; + _release_fcn = &release_nop; + return release_fcn(); } private: @@ -50,64 +53,42 @@ private: } const boost::asio::const_buffer _buff; + release_fcn_t _release_fcn; }; -//! phony zero-copy recv interface implementation -struct phony_zero_copy_recv_if::impl{ - impl(size_t max_buff_size) : max_buff_size(max_buff_size){ - /* NOP */ - } - size_t max_buff_size; -}; - -phony_zero_copy_recv_if::phony_zero_copy_recv_if(size_t max_buff_size){ - _impl = UHD_PIMPL_MAKE(impl, (max_buff_size)); -} - -phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ - /* NOP */ -} - -managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(double timeout){ - //allocate memory - boost::uint8_t *recv_mem = new boost::uint8_t[_impl->max_buff_size]; - - //call recv() with timeout option - ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size), timeout); - - if (num_bytes <= 0) return managed_recv_buffer::sptr(); //NULL sptr - - //create a new managed buffer to house the data - return managed_recv_buffer::sptr( - new managed_recv_buffer_impl(boost::asio::buffer(recv_mem, num_bytes)) - ); +managed_recv_buffer::sptr managed_recv_buffer::make_safe( + const boost::asio::const_buffer &buff, + const release_fcn_t &release_fcn +){ + return sptr(new safe_managed_receive_buffer(buff, release_fcn)); } /*********************************************************************** - * Phony zero-copy send interface implementation + * Safe managed send buffer **********************************************************************/ +static void commit_nop(size_t){ + /* NOP */ +} -//! phony zero-copy send buffer implementation -class managed_send_buffer_impl : public managed_send_buffer{ +class safe_managed_send_buffer : public managed_send_buffer{ public: - typedef boost::function send_fcn_t; - - managed_send_buffer_impl( + safe_managed_send_buffer( const boost::asio::mutable_buffer &buff, - const send_fcn_t &send_fcn + const commit_fcn_t &commit_fcn ): - _buff(buff), - _send_fcn(send_fcn) + _buff(buff), _commit_fcn(commit_fcn) { /* NOP */ } - ~managed_send_buffer_impl(void){ - /* NOP */ + ~safe_managed_send_buffer(void){ + _commit_fcn(0); } - ssize_t commit(size_t num_bytes){ - return _send_fcn(boost::asio::buffer(_buff, num_bytes)); + void commit(size_t num_bytes){ + commit_fcn_t commit_fcn = _commit_fcn; + _commit_fcn = &commit_nop; + return commit_fcn(num_bytes); } private: @@ -116,28 +97,12 @@ private: } const boost::asio::mutable_buffer _buff; - const send_fcn_t _send_fcn; -}; - -//! phony zero-copy send interface implementation -struct phony_zero_copy_send_if::impl{ - boost::uint8_t *send_mem; - managed_send_buffer::sptr send_buff; + commit_fcn_t _commit_fcn; }; -phony_zero_copy_send_if::phony_zero_copy_send_if(size_t max_buff_size){ - _impl = UHD_PIMPL_MAKE(impl, ()); - _impl->send_mem = new boost::uint8_t[max_buff_size]; - _impl->send_buff = managed_send_buffer::sptr(new managed_send_buffer_impl( - boost::asio::buffer(_impl->send_mem, max_buff_size), - boost::bind(&phony_zero_copy_send_if::send, this, _1) - )); -} - -phony_zero_copy_send_if::~phony_zero_copy_send_if(void){ - delete [] _impl->send_mem; -} - -managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(double){ - return _impl->send_buff; //FIXME there is only ever one send buff, we assume that the caller doesnt hang onto these +safe_managed_send_buffer::sptr managed_send_buffer::make_safe( + const boost::asio::mutable_buffer &buff, + const commit_fcn_t &commit_fcn +){ + return sptr(new safe_managed_send_buffer(buff, commit_fcn)); } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 8d9c68961..676b1536a 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,35 +33,6 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -/*********************************************************************** - * Pseudo send buffer implementation - **********************************************************************/ -class pseudo_managed_send_buffer : public managed_send_buffer{ -public: - - pseudo_managed_send_buffer( - const boost::asio::mutable_buffer &buff, - const boost::function &commit - ): - _buff(buff), - _commit(commit) - { - /* NOP */ - } - - ssize_t commit(size_t num_bytes){ - return _commit(num_bytes); - } - -private: - const boost::asio::mutable_buffer &get(void) const{ - return _buff; - } - - const boost::asio::mutable_buffer _buff; - const boost::function _commit; -}; - /*********************************************************************** * IO Implementation Details **********************************************************************/ @@ -96,9 +67,9 @@ struct usrp1_impl::io_impl{ size_t num_bytes_committed; double send_timeout; boost::uint8_t pseudo_buff[BYTES_PER_PACKET]; - ssize_t phony_commit_pseudo_buff(size_t num_bytes); - ssize_t phony_commit_send_buff(size_t num_bytes); - ssize_t commit_send_buff(void); + void phony_commit_pseudo_buff(size_t num_bytes); + void phony_commit_send_buff(size_t num_bytes); + void commit_send_buff(void); void flush_send_buff(void); bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &, double); @@ -119,28 +90,25 @@ struct usrp1_impl::io_impl{ * The first loop iteration will fill the remainder of the send buffer. * The second loop iteration will empty the pseudo buffer remainder. */ -ssize_t usrp1_impl::io_impl::phony_commit_pseudo_buff(size_t num_bytes){ +void usrp1_impl::io_impl::phony_commit_pseudo_buff(size_t num_bytes){ size_t bytes_to_copy = num_bytes, bytes_copied = 0; while(bytes_to_copy){ size_t bytes_copied_here = std::min(bytes_to_copy, get_send_mem_size()); std::memcpy(get_send_mem_ptr(), pseudo_buff + bytes_copied, bytes_copied_here); - ssize_t ret = phony_commit_send_buff(bytes_copied_here); - if (ret < 0) return ret; - bytes_to_copy -= ret; - bytes_copied += ret; + phony_commit_send_buff(bytes_copied_here); + bytes_to_copy -= bytes_copied_here; + bytes_copied += bytes_copied_here; } - return bytes_copied; } /*! * Accept a commit of num bytes to the send buffer. * Conditionally commit the send buffer if full. */ -ssize_t usrp1_impl::io_impl::phony_commit_send_buff(size_t num_bytes){ +void usrp1_impl::io_impl::phony_commit_send_buff(size_t num_bytes){ num_bytes_committed += num_bytes; - if (num_bytes_committed != send_buff->size()) return num_bytes; - ssize_t ret = commit_send_buff(); - return (ret < 0)? ret : num_bytes; + if (num_bytes_committed != send_buff->size()) return; + commit_send_buff(); } /*! @@ -158,11 +126,10 @@ void usrp1_impl::io_impl::flush_send_buff(void){ * Perform an actual commit on the send buffer: * Commit the contents of the send buffer and request a new buffer. */ -ssize_t usrp1_impl::io_impl::commit_send_buff(void){ - ssize_t ret = send_buff->commit(num_bytes_committed); +void usrp1_impl::io_impl::commit_send_buff(void){ + send_buff->commit(num_bytes_committed); send_buff = data_transport->get_send_buff(send_timeout); num_bytes_committed = 0; - return ret; } bool usrp1_impl::io_impl::get_send_buffs( @@ -173,17 +140,17 @@ bool usrp1_impl::io_impl::get_send_buffs( //not enough bytes free -> use the pseudo buffer if (get_send_mem_size() < BYTES_PER_PACKET){ - buffs[0] = managed_send_buffer::sptr(new pseudo_managed_send_buffer( + buffs[0] = managed_send_buffer::make_safe( boost::asio::buffer(pseudo_buff), boost::bind(&usrp1_impl::io_impl::phony_commit_pseudo_buff, this, _1) - )); + ); } //otherwise use the send buffer offset by the bytes written else{ - buffs[0] = managed_send_buffer::sptr(new pseudo_managed_send_buffer( + buffs[0] = managed_send_buffer::make_safe( boost::asio::buffer(get_send_mem_ptr(), get_send_mem_size()), boost::bind(&usrp1_impl::io_impl::phony_commit_send_buff, this, _1) - )); + ); } return buffs[0].get() != NULL; -- cgit v1.2.3 From 5bd863efa05f3c6cfd672cffe87f57b33d1c32b5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 14:54:16 -0700 Subject: uhd: bounded buffer pop sets back element to empty to decrement references --- host/include/uhd/transport/bounded_buffer.ipp | 16 ++++++++++++++-- host/lib/transport/libusb1_zero_copy.cpp | 4 ---- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp index 71143741e..58f78bab4 100644 --- a/host/include/uhd/transport/bounded_buffer.ipp +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -73,7 +73,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE void pop_with_wait(elem_type &elem){ boost::unique_lock lock(_mutex); _empty_cond.wait(lock, boost::bind(&bounded_buffer_impl::not_empty, this)); - elem = _buffer.back(); _buffer.pop_back(); + this->pop_back(elem); lock.unlock(); _full_cond.notify_one(); } @@ -84,7 +84,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ lock, boost::posix_time::microseconds(long(timeout*1e6)), boost::bind(&bounded_buffer_impl::not_empty, this) )) return false; - elem = _buffer.back(); _buffer.pop_back(); + this->pop_back(elem); lock.unlock(); _full_cond.notify_one(); return true; @@ -104,6 +104,18 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ bool not_full(void) const{return not _buffer.full();} bool not_empty(void) const{return not _buffer.empty();} + + /*! + * Three part operation to pop an element: + * 1) assign elem to the back element + * 2) assign the back element to empty + * 3) pop the back to move the counter + */ + UHD_INLINE void pop_back(elem_type &elem){ + elem = _buffer.back(); + _buffer.back() = elem_type(); + _buffer.pop_back(); + } }; }}} //namespace diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index c7f084f62..819874483 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -335,10 +335,6 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; - //sanity check the transfer sizes - UHD_ASSERT_THROW(recv_xfer_size % 512 == 0); - UHD_ASSERT_THROW(send_xfer_size % 512 == 0); - //store the num xfers for the num frames count _recv_xfer_size = recv_xfer_size; _recv_num_frames = recv_num_xfers; -- cgit v1.2.3 From 0cd5375b5c8a928f112a963d9c9c2556bafed108 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 5 Oct 2010 10:30:28 -0700 Subject: uhd: replaced frame params for the zero copy interfaces with a device address the device address gives a key, value pair of infinite optional capabilities added a cast option to the device address to cast string to type T added call to the zero_copy_if to get send and recv frame sizes changed the usrp2 impl to calculate recv/send spp from the data transport --- host/include/uhd/transport/udp_zero_copy.hpp | 7 ++- host/include/uhd/transport/usb_control.hpp | 2 +- host/include/uhd/transport/usb_zero_copy.hpp | 17 +++---- host/include/uhd/transport/zero_copy.hpp | 26 +++++++--- host/include/uhd/types/device_addr.hpp | 20 ++++++++ host/lib/transport/libusb1_zero_copy.cpp | 67 +++++++++++-------------- host/lib/transport/udp_zero_copy_asio.cpp | 35 +++++++------ host/lib/transport/usb_dummy_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 48 +++++++----------- host/lib/usrp/usrp2/io_impl.cpp | 4 +- host/lib/usrp/usrp2/mboard_impl.cpp | 8 +-- host/lib/usrp/usrp2/usrp2_impl.cpp | 40 ++++++--------- host/lib/usrp/usrp2/usrp2_impl.hpp | 75 ++++++++-------------------- 13 files changed, 162 insertions(+), 191 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp index 818709973..bbba97b21 100644 --- a/host/include/uhd/transport/udp_zero_copy.hpp +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -20,6 +20,7 @@ #include #include +#include #include namespace uhd{ namespace transport{ @@ -50,14 +51,12 @@ public: * * \param addr a string representing the destination address * \param port a string representing the destination port - * \param recv_buff_size size in bytes for the recv buffer, 0 for automatic - * \param send_buff_size size in bytes for the send buffer, 0 for automatic + * \param hints optional parameters to pass to the underlying transport */ static sptr make( const std::string &addr, const std::string &port, - size_t recv_buff_size = 0, - size_t send_buff_size = 0 + const device_addr_t &hints = device_addr_t() ); }; diff --git a/host/include/uhd/transport/usb_control.hpp b/host/include/uhd/transport/usb_control.hpp index f9829c3ec..e6c32f78e 100644 --- a/host/include/uhd/transport/usb_control.hpp +++ b/host/include/uhd/transport/usb_control.hpp @@ -18,7 +18,7 @@ #ifndef INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP #define INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP -#include "usb_device_handle.hpp" +#include namespace uhd { namespace transport { diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp index 61bf380ba..b39171fba 100644 --- a/host/include/uhd/transport/usb_zero_copy.hpp +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -18,8 +18,9 @@ #ifndef INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP #define INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP -#include "usb_device_handle.hpp" +#include #include +#include namespace uhd { namespace transport { @@ -47,19 +48,13 @@ public: * \param handle a device handle that uniquely identifying the device * \param recv_endpoint an integer specifiying an IN endpoint number * \param send_endpoint an integer specifiying an OUT endpoint number - * \param recv_xfer_size the number of bytes for each receive transfer - * \param recv_num_xfers the number of simultaneous receive transfers - * \param send_xfer_size the number of bytes for each send transfer - * \param send_num_xfers the number of simultaneous send transfers + * \param hints optional parameters to pass to the underlying transport */ static sptr make( usb_device_handle::sptr handle, - unsigned int recv_endpoint, - unsigned int send_endpoint, - size_t recv_xfer_size = 0, - size_t recv_num_xfers = 0, - size_t send_xfer_size = 0, - size_t send_num_xfers = 0 + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints = device_addr_t() ); }; diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 9dd16280c..7d8fb4b83 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -155,14 +155,19 @@ namespace uhd{ namespace transport{ virtual managed_recv_buffer::sptr get_recv_buff(double timeout = 0.1) = 0; /*! - * Get the maximum number of receive frames: - * The maximum number of valid managed recv buffers, - * or the maximum number of frames in the ring buffer, - * depending upon the underlying implementation. + * Get the number of receive frames: + * The number of simultaneous receive buffers in use. * \return number of frames */ virtual size_t get_num_recv_frames(void) const = 0; + /*! + * Get the size of a receive frame: + * The maximum capacity of a single receive buffer. + * \return frame size in bytes + */ + virtual size_t get_recv_frame_size(void) const = 0; + /*! * Get a new send buffer from this transport object. * \param timeout the timeout to get the buffer in seconds @@ -171,14 +176,19 @@ namespace uhd{ namespace transport{ virtual managed_send_buffer::sptr get_send_buff(double timeout = 0.1) = 0; /*! - * Get the maximum number of send frames: - * The maximum number of valid managed send buffers, - * or the maximum number of frames in the ring buffer, - * depending upon the underlying implementation. + * Get the number of send frames: + * The number of simultaneous send buffers in use. * \return number of frames */ virtual size_t get_num_send_frames(void) const = 0; + /*! + * Get the size of a send frame: + * The maximum capacity of a single send buffer. + * \return frame size in bytes + */ + virtual size_t get_send_frame_size(void) const = 0; + }; }} //namespace diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp index e359d9467..eb3394230 100644 --- a/host/include/uhd/types/device_addr.hpp +++ b/host/include/uhd/types/device_addr.hpp @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include @@ -62,6 +64,24 @@ namespace uhd{ * \return a string with delimiter markup */ std::string to_string(void) const; + + /*! + * Lexically cast a parameter to the specified type, + * or use the default value if the key is not found. + * \param key the key as one of the address parameters + * \param def the value to use when key is not present + * \return the casted value as type T or the default + * \throw error when the parameter cannot be casted + */ + template T cast(const std::string &key, const T &def) const{ + if (not this->has_key(key)) return def; + try{ + return boost::lexical_cast((*this)[key]); + } + catch(const boost::bad_lexical_cast &){ + throw std::runtime_error("cannot cast " + key + " = " + (*this)[key]); + } + } }; //handy typedef for a vector of device addresses diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 819874483..df6db1eb9 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -26,6 +26,7 @@ #include #include +using namespace uhd; using namespace uhd::transport; static const double CLEANUP_TIMEOUT = 0.2; //seconds @@ -284,16 +285,19 @@ public: libusb_zero_copy_impl( libusb::device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints ); managed_recv_buffer::sptr get_recv_buff(double); managed_send_buffer::sptr get_send_buff(double); - size_t get_num_recv_frames(void) const { return _recv_num_frames; } - size_t get_num_send_frames(void) const { return _send_num_frames; } + size_t get_num_recv_frames(void) const { return _num_recv_frames; } + size_t get_num_send_frames(void) const { return _num_send_frames; } + + size_t get_recv_frame_size(void) const { return _recv_frame_size; } + size_t get_send_frame_size(void) const { return _send_frame_size; } private: void release(libusb_transfer *lut){ @@ -311,8 +315,8 @@ private: } libusb::device_handle::sptr _handle; - size_t _recv_xfer_size, _send_xfer_size; - size_t _recv_num_frames, _send_num_frames; + const size_t _recv_frame_size, _num_recv_frames; + const size_t _send_frame_size, _num_send_frames; usb_endpoint::sptr _recv_ep, _send_ep; }; @@ -323,24 +327,16 @@ private: */ libusb_zero_copy_impl::libusb_zero_copy_impl( libusb::device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers -){ - _handle = handle; - - //if the sizes are left at 0 (automatic) -> use the defaults - if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE; - if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS; - if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; - if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; - - //store the num xfers for the num frames count - _recv_xfer_size = recv_xfer_size; - _recv_num_frames = recv_num_xfers; - _send_xfer_size = send_xfer_size; - _send_num_frames = send_num_xfers; - + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints +): + _handle(handle), + _recv_frame_size(size_t(hints.cast("recv_frame_size", DEFAULT_XFER_SIZE))), + _num_recv_frames(size_t(hints.cast("num_recv_frames", DEFAULT_NUM_XFERS))), + _send_frame_size(size_t(hints.cast("send_frame_size", DEFAULT_XFER_SIZE))), + _num_send_frames(size_t(hints.cast("num_send_frames", DEFAULT_NUM_XFERS))) +{ _handle->claim_interface(2 /*in interface*/); _handle->claim_interface(1 /*out interface*/); @@ -348,16 +344,16 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( _handle, // libusb device_handle recv_endpoint, // USB endpoint number true, // IN endpoint - recv_xfer_size, // buffer size per transfer - recv_num_xfers // number of libusb transfers + this->get_recv_frame_size(), // buffer size per transfer + this->get_num_recv_frames() // number of libusb transfers )); _send_ep = usb_endpoint::sptr(new usb_endpoint( _handle, // libusb device_handle send_endpoint, // USB endpoint number false, // OUT endpoint - send_xfer_size, // buffer size per transfer - send_num_xfers // number of libusb transfers + this->get_send_frame_size(), // buffer size per transfer + this->get_num_send_frames() // number of libusb transfers )); } @@ -394,7 +390,7 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ } else { return managed_send_buffer::make_safe( - boost::asio::mutable_buffer(lut->buffer, _send_xfer_size), + boost::asio::mutable_buffer(lut->buffer, this->get_send_frame_size()), boost::bind(&libusb_zero_copy_impl::commit, shared_from_this(), lut, _1) ); } @@ -405,17 +401,14 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ **********************************************************************/ usb_zero_copy::sptr usb_zero_copy::make( usb_device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints ){ libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( boost::static_pointer_cast(handle)->get_device() )); return sptr(new libusb_zero_copy_impl( - dev_handle, - recv_endpoint, send_endpoint, - recv_xfer_size, recv_num_xfers, - send_xfer_size, send_num_xfers + dev_handle, recv_endpoint, send_endpoint, hints )); } diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index e9d91fe45..ada282e07 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -44,7 +44,7 @@ static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3); //the number of async frames to allocate for each send and recv -static const size_t DEFAULT_NUM_ASYNC_FRAMES = 32; +static const size_t DEFAULT_NUM_FRAMES = 32; //a single concurrent thread for io_service seems to be the fastest static const size_t CONCURRENCY_HINT = 1; @@ -61,14 +61,15 @@ public: typedef boost::shared_ptr sptr; udp_zero_copy_asio_impl( - const std::string &addr, const std::string &port, - size_t recv_frame_size, size_t num_recv_frames, - size_t send_frame_size, size_t num_send_frames + const std::string &addr, + const std::string &port, + const device_addr_t &hints ): - _io_service(CONCURRENCY_HINT), - _work(new asio::io_service::work(_io_service)), - _recv_frame_size(recv_frame_size), _num_recv_frames(num_recv_frames), - _send_frame_size(send_frame_size), _num_send_frames(num_send_frames) + _io_service(hints.cast("concurrency_hint", CONCURRENCY_HINT)), + _recv_frame_size(size_t(hints.cast("recv_frame_size", udp_simple::mtu))), + _num_recv_frames(size_t(hints.cast("num_recv_frames", DEFAULT_NUM_FRAMES))), + _send_frame_size(size_t(hints.cast("send_frame_size", udp_simple::mtu))), + _num_send_frames(size_t(hints.cast("num_send_frames", DEFAULT_NUM_FRAMES))) { //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; @@ -99,6 +100,7 @@ public: } //spawn the service threads that will run the io service + _work = new asio::io_service::work(_io_service); //new work to delete later for (size_t i = 0; i < CONCURRENCY_HINT; i++) _thread_group.create_thread( boost::bind(&udp_zero_copy_asio_impl::service, this) ); @@ -141,6 +143,7 @@ public: } size_t get_num_recv_frames(void) const {return _num_recv_frames;} + size_t get_recv_frame_size(void) const {return _recv_frame_size;} //! pop an empty send buffer off of the fifo and bind with the commit callback managed_send_buffer::sptr get_send_buff(double timeout){ @@ -159,6 +162,7 @@ public: } size_t get_num_send_frames(void) const {return _num_send_frames;} + size_t get_send_frame_size(void) const {return _send_frame_size;} private: void service(void){ @@ -260,14 +264,15 @@ template static void resize_buff_helper( udp_zero_copy::sptr udp_zero_copy::make( const std::string &addr, const std::string &port, - size_t recv_buff_size, - size_t send_buff_size + const device_addr_t &hints ){ - udp_zero_copy_asio_impl::sptr udp_trans(new udp_zero_copy_asio_impl( - addr, port, - udp_simple::mtu, DEFAULT_NUM_ASYNC_FRAMES, //recv - udp_simple::mtu, DEFAULT_NUM_ASYNC_FRAMES //send - )); + udp_zero_copy_asio_impl::sptr udp_trans( + new udp_zero_copy_asio_impl(addr, port, hints) + ); + + //extract buffer size hints from the device addr + size_t recv_buff_size = size_t(hints.cast("recv_buff_size", 0.0)); + size_t send_buff_size = size_t(hints.cast("send_buff_size", 0.0)); //call the helper to resize send and recv buffers resize_buff_helper(udp_trans, recv_buff_size, "recv"); diff --git a/host/lib/transport/usb_dummy_impl.cpp b/host/lib/transport/usb_dummy_impl.cpp index 518342aba..8a9772e7f 100644 --- a/host/lib/transport/usb_dummy_impl.cpp +++ b/host/lib/transport/usb_dummy_impl.cpp @@ -20,6 +20,7 @@ #include #include +using namespace uhd; using namespace uhd::transport; std::vector usb_device_handle::get_device_list(boost::uint16_t, boost::uint16_t){ @@ -32,8 +33,7 @@ usb_control::sptr usb_control::make(usb_device_handle::sptr){ usb_zero_copy::sptr usb_zero_copy::make( usb_device_handle::sptr, - unsigned int, unsigned int, - size_t, size_t, size_t, size_t + size_t, size_t, const device_addr_t & ){ throw std::runtime_error("no usb support -> usb_zero_copy::make not implemented"); } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 6ebd6bb09..276ca86f6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -106,17 +106,8 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) /*********************************************************************** * Make **********************************************************************/ -template static output_type cast_from_dev_addr( - const device_addr_t &device_addr, - const std::string &key, - output_type def_val -){ - return (device_addr.has_key(key))? - boost::lexical_cast(device_addr[key]) : def_val; -} +static device::sptr usrp1_make(const device_addr_t &device_addr){ -static device::sptr usrp1_make(const device_addr_t &device_addr) -{ //extract the FPGA path for the USRP1 std::string usrp1_fpga_image = find_image_path( device_addr.has_key("fpga")? device_addr["fpga"] : "usrp1_fpga.rbf" @@ -127,29 +118,26 @@ static device::sptr usrp1_make(const device_addr_t &device_addr) std::vector device_list = usb_device_handle::get_device_list(USRP1_VENDOR_ID, USRP1_PRODUCT_ID); - //create data and control transports - usb_zero_copy::sptr data_transport; - usrp_ctrl::sptr usrp_ctrl; - - - BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { - if (handle->get_serial() == device_addr["serial"]) { - usb_control::sptr ctrl_transport = usb_control::make(handle); - usrp_ctrl = usrp_ctrl::make(ctrl_transport); - usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); - - data_transport = usb_zero_copy::make( - handle, // identifier - 6, // IN endpoint - 2, // OUT endpoint - size_t(cast_from_dev_addr(device_addr, "recv_xfer_size", 0)), - size_t(cast_from_dev_addr(device_addr, "recv_num_xfers", 0)), - size_t(cast_from_dev_addr(device_addr, "send_xfer_size", 0)), - size_t(cast_from_dev_addr(device_addr, "send_num_xfers", 0)) - ); + //locate the matching handle in the device list + usb_device_handle::sptr handle; + BOOST_FOREACH(usb_device_handle::sptr dev_handle, device_list) { + if (dev_handle->get_serial() == device_addr["serial"]){ + handle = dev_handle; break; } } + UHD_ASSERT_THROW(handle.get() != NULL); //better be found + + //create control objects and a data transport + usb_control::sptr ctrl_transport = usb_control::make(handle); + usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); + usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); + usb_zero_copy::sptr data_transport = usb_zero_copy::make( + handle, // identifier + 6, // IN endpoint + 2, // OUT endpoint + device_addr // param hints + ); //create the usrp1 implementation guts return device::sptr(new usrp1_impl(data_transport, usrp_ctrl)); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 33cec3cbc..07eda08c3 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -206,7 +206,7 @@ size_t usrp2_impl::send( _io_impl->packet_handler_send_state, //last state of the send handler buffs, num_samps, //buffer to fill metadata, send_mode, //samples metadata - io_type, _io_helper.get_tx_otw_type(), //input and output types to convert + io_type, _tx_otw_type, //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_pack_be, boost::bind(&get_send_buffs, _data_transports, _1, timeout), @@ -226,7 +226,7 @@ size_t usrp2_impl::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler buffs, num_samps, //buffer to fill metadata, recv_mode, //samples metadata - io_type, _io_helper.get_rx_otw_type(), //input and output types to convert + io_type, _rx_otw_type, //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_be, boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout) diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 0b9f8ee83..a0e6adfad 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -38,10 +38,10 @@ using namespace uhd::usrp; usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, - const usrp2_io_helper &io_helper + size_t recv_frame_size ): _index(index), - _io_helper(io_helper) + _recv_frame_size(recv_frame_size) { //make a new interface for usrp2 stuff _iface = usrp2_iface::make(ctrl_transport); @@ -75,7 +75,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); //init the rx control registers - _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _io_helper.get_max_recv_samps_per_packet()); + _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _recv_frame_size); _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset _iface->poke32(U2_REG_RX_CTRL_VRT_HEADER, 0 @@ -178,7 +178,7 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){ void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word( - stream_cmd, _io_helper.get_max_recv_samps_per_packet() + stream_cmd, _recv_frame_size )); _iface->poke32(U2_REG_RX_CTRL_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); _iface->poke32(U2_REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 568c87a22..a680708ad 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -124,26 +124,7 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ /*********************************************************************** * Make **********************************************************************/ -template -out_type lexical_cast(const in_type &in){ - try{ - return boost::lexical_cast(in); - }catch(...){ - throw std::runtime_error(str(boost::format( - "failed to cast \"%s\" to type \"%s\"" - ) % boost::lexical_cast(in) % typeid(out_type).name())); - } -} - static device::sptr usrp2_make(const device_addr_t &device_addr){ - //extract the receive and send buffer sizes - size_t recv_buff_size = 0, send_buff_size= 0 ; - if (device_addr.has_key("recv_buff_size")){ - recv_buff_size = size_t(lexical_cast(device_addr["recv_buff_size"])); - } - if (device_addr.has_key("send_buff_size")){ - send_buff_size = size_t(lexical_cast(device_addr["send_buff_size"])); - } //create a ctrl and data transport for each address std::vector ctrl_transports; @@ -154,8 +135,7 @@ static device::sptr usrp2_make(const device_addr_t &device_addr){ addr, num2str(USRP2_UDP_CTRL_PORT) )); data_transports.push_back(udp_zero_copy::make( - addr, num2str(USRP2_UDP_DATA_PORT), - recv_buff_size, send_buff_size + addr, num2str(USRP2_UDP_DATA_PORT), device_addr )); } @@ -178,11 +158,23 @@ usrp2_impl::usrp2_impl( ): _data_transports(data_transports) { + //setup rx otw type + _rx_otw_type.width = 16; + _rx_otw_type.shift = 0; + _rx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + + //setup tx otw type + _tx_otw_type.width = 16; + _tx_otw_type.shift = 0; + _tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + + //!!!!! set the otw type here before continuing, its used below + //create a new mboard handler for each control transport for(size_t i = 0; i < ctrl_transports.size(); i++){ - _mboards.push_back(usrp2_mboard_impl::sptr( - new usrp2_mboard_impl(i, ctrl_transports[i], _io_helper) - )); + _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( + i, ctrl_transports[i], this->get_max_recv_samps_per_packet() + ))); //use an empty name when there is only one mboard std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast(i) : ""; _mboard_dict[name] = _mboards.back(); diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index e8763b284..e12c4d6d4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -71,54 +71,6 @@ private: void set(const wax::obj &key, const wax::obj &val){return _set(key, val);} }; -/*! - * The io helper class encapculates the max packet sizes and otw types. - * The otw types are read-only for now, this will be reimplemented - * when it becomes possible to change the otw type in the usrp2. - */ -class usrp2_io_helper{ -public: - usrp2_io_helper(void){ - //setup rx otw type - _rx_otw_type.width = 16; - _rx_otw_type.shift = 0; - _rx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; - - //setup tx otw type - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; - } - - inline size_t get_max_send_samps_per_packet(void) const{ - return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size(); - } - - inline size_t get_max_recv_samps_per_packet(void) const{ - return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size(); - } - - inline const uhd::otw_type_t &get_rx_otw_type(void) const{ - return _rx_otw_type; - } - - inline const uhd::otw_type_t &get_tx_otw_type(void) const{ - return _tx_otw_type; - } - -private: - uhd::otw_type_t _rx_otw_type, _tx_otw_type; - static const size_t _max_rx_bytes_per_packet = uhd::transport::udp_simple::mtu - - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - - sizeof(uhd::transport::vrt::if_packet_info_t().tlr) //forced to have trailer - + sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used - ; - static const size_t _max_tx_bytes_per_packet = uhd::transport::udp_simple::mtu - - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used - ; -}; - /*! * USRP2 mboard implementation guts: * The implementation details are encapsulated here. @@ -129,7 +81,11 @@ public: typedef boost::shared_ptr sptr; //structors - usrp2_mboard_impl(size_t index, uhd::transport::udp_simple::sptr, const usrp2_io_helper &); + usrp2_mboard_impl( + size_t index, + uhd::transport::udp_simple::sptr, + size_t recv_frame_size + ); ~usrp2_mboard_impl(void); inline double get_master_clock_freq(void){ @@ -139,7 +95,7 @@ public: private: size_t _index; int _rev_hi, _rev_lo; - const usrp2_io_helper &_io_helper; + const size_t _recv_frame_size; //properties for this mboard void get(const wax::obj &, wax::obj &); @@ -229,7 +185,8 @@ public: //the io interface size_t get_max_send_samps_per_packet(void) const{ - return _io_helper.get_max_send_samps_per_packet(); + const size_t bytes_per_packet = _data_transports.front()->get_send_frame_size() - _max_tx_header_bytes; + return bytes_per_packet/_tx_otw_type.get_sample_size(); } size_t send( const std::vector &, size_t, @@ -237,7 +194,8 @@ public: uhd::device::send_mode_t, double ); size_t get_max_recv_samps_per_packet(void) const{ - return _io_helper.get_max_recv_samps_per_packet(); + const size_t bytes_per_packet = _data_transports.front()->get_recv_frame_size() - _max_rx_header_bytes; + return bytes_per_packet/_rx_otw_type.get_sample_size(); } size_t recv( const std::vector &, size_t, @@ -257,9 +215,20 @@ private: //io impl methods and members std::vector _data_transports; - const usrp2_io_helper _io_helper; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); + + //over-the-wire structs and constants + uhd::otw_type_t _rx_otw_type, _tx_otw_type; + static const size_t _max_rx_header_bytes = 0 + + uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(uhd::transport::vrt::if_packet_info_t().tlr) //forced to have trailer + - sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used + ; + static const size_t _max_tx_header_bytes = 0 + + uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + - sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used + ; }; #endif /* INCLUDED_USRP2_IMPL_HPP */ -- cgit v1.2.3 From 12901b055f021acf1b02f4bc7e9c3c8d1aa426e5 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 6 Oct 2010 18:48:03 -0400 Subject: Add flag that indicates userspace has started processing a frame. --- host/include/linux/usrp_e.h | 1 + 1 file changed, 1 insertion(+) (limited to 'host/include') diff --git a/host/include/linux/usrp_e.h b/host/include/linux/usrp_e.h index 80f3a287b..cb62d940d 100644 --- a/host/include/linux/usrp_e.h +++ b/host/include/linux/usrp_e.h @@ -71,6 +71,7 @@ struct usrp_e_i2c { #define RB_KERNEL (1<<1) #define RB_OVERRUN (1<<2) #define RB_DMA_ACTIVE (1<<3) +#define RB_USER_PROCESS (1<<4) struct ring_buffer_info { int flags; -- cgit v1.2.3 From e8e9258acb8ce8499c40de52abaa4e6ba83d479d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 11:20:30 -0700 Subject: udp: worked blocking send back into udp transport, enable async with #define tweaked some code in bounded buffer --- host/include/uhd/transport/alignment_buffer.ipp | 8 +- host/include/uhd/transport/bounded_buffer.ipp | 39 +++++--- host/lib/transport/udp_zero_copy_asio.cpp | 114 +++++++++++++++--------- 3 files changed, 99 insertions(+), 62 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp index 5f09de0d9..833b5d399 100644 --- a/host/include/uhd/transport/alignment_buffer.ipp +++ b/host/include/uhd/transport/alignment_buffer.ipp @@ -54,14 +54,14 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE bool pop_elems_with_timed_wait( std::vector &elems, double timeout ){ - boost::system_time exit_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1e6)); + boost::system_time exit_time = boost::get_system_time() + to_time_dur(timeout); buff_contents_type buff_contents_tmp; std::list indexes_to_do(_all_indexes); //do an initial pop to load an initial sequence id size_t index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() + buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) )) return false; elems[index] = buff_contents_tmp.first; seq_type expected_seq_id = buff_contents_tmp.second; @@ -76,7 +76,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ indexes_to_do = _all_indexes; index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() + buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) )) return false; elems[index] = buff_contents_tmp.first; expected_seq_id = buff_contents_tmp.second; @@ -86,7 +86,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ //pop an element off for this index index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() + buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) )) return false; //if the sequence id matches: diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp index 58f78bab4..edc7faa06 100644 --- a/host/include/uhd/transport/bounded_buffer.ipp +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -19,18 +19,28 @@ #define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP #include +#include #include #include #include namespace uhd{ namespace transport{ namespace{ /*anon*/ + static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){ + return boost::posix_time::microseconds(long(timeout*1e6)); + } + + static UHD_INLINE double from_time_dur(const boost::posix_time::time_duration &time_dur){ + return 1e-6*time_dur.total_microseconds(); + } + template class bounded_buffer_impl : public bounded_buffer{ public: bounded_buffer_impl(size_t capacity) : _buffer(capacity){ - /* NOP */ + _not_full_fcn = boost::bind(&bounded_buffer_impl::not_full, this); + _not_empty_fcn = boost::bind(&bounded_buffer_impl::not_empty, this); } UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){ @@ -52,17 +62,16 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE void push_with_wait(const elem_type &elem){ boost::unique_lock lock(_mutex); - _full_cond.wait(lock, boost::bind(&bounded_buffer_impl::not_full, this)); + _full_cond.wait(lock, _not_full_fcn); _buffer.push_front(elem); lock.unlock(); _empty_cond.notify_one(); } - bool push_with_timed_wait(const elem_type &elem, double timeout){ + UHD_INLINE bool push_with_timed_wait(const elem_type &elem, double timeout){ boost::unique_lock lock(_mutex); if (not _full_cond.timed_wait( - lock, boost::posix_time::microseconds(long(timeout*1e6)), - boost::bind(&bounded_buffer_impl::not_full, this) + lock, to_time_dur(timeout), _not_full_fcn )) return false; _buffer.push_front(elem); lock.unlock(); @@ -72,19 +81,18 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE void pop_with_wait(elem_type &elem){ boost::unique_lock lock(_mutex); - _empty_cond.wait(lock, boost::bind(&bounded_buffer_impl::not_empty, this)); - this->pop_back(elem); + _empty_cond.wait(lock, _not_empty_fcn); + elem = this->pop_back(); lock.unlock(); _full_cond.notify_one(); } - bool pop_with_timed_wait(elem_type &elem, double timeout){ + UHD_INLINE bool pop_with_timed_wait(elem_type &elem, double timeout){ boost::unique_lock lock(_mutex); if (not _empty_cond.timed_wait( - lock, boost::posix_time::microseconds(long(timeout*1e6)), - boost::bind(&bounded_buffer_impl::not_empty, this) + lock, to_time_dur(timeout), _not_empty_fcn )) return false; - this->pop_back(elem); + elem = this->pop_back(); lock.unlock(); _full_cond.notify_one(); return true; @@ -92,7 +100,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE void clear(void){ boost::unique_lock lock(_mutex); - while (not_empty()) _buffer.pop_back(); + while (not_empty()) this->pop_back(); lock.unlock(); _full_cond.notify_one(); } @@ -105,16 +113,19 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ bool not_full(void) const{return not _buffer.full();} bool not_empty(void) const{return not _buffer.empty();} + boost::function _not_full_fcn, _not_empty_fcn; + /*! * Three part operation to pop an element: * 1) assign elem to the back element * 2) assign the back element to empty * 3) pop the back to move the counter */ - UHD_INLINE void pop_back(elem_type &elem){ - elem = _buffer.back(); + UHD_INLINE elem_type pop_back(void){ + elem_type elem = _buffer.back(); _buffer.back() = elem_type(); _buffer.pop_back(); + return elem; } }; }}} //namespace diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 40fe3fa0f..d84aeefdd 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -39,6 +39,10 @@ namespace asio = boost::asio; //Otherwise, get_recv_buff uses a blocking receive with timeout. //#define USE_ASIO_ASYNC_RECV +//Define this to the the boost async io calls to perform send. +//Otherwise, the commit callback uses a blocking send. +//#define USE_ASIO_ASYNC_SEND + //enough buffering for half a second of samples at full rate on usrp2 static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); @@ -55,7 +59,13 @@ static const size_t DEFAULT_NUM_RECV_FRAMES = 32; #else static const size_t DEFAULT_NUM_RECV_FRAMES = MIN_RECV_SOCK_BUFF_SIZE/udp_simple::mtu; #endif +//The non-async send only ever requires a single frame +//because the buffer will be committed before a new get. +#ifdef USE_ASIO_ASYNC_SEND static const size_t DEFAULT_NUM_SEND_FRAMES = 32; +#else +static const size_t DEFAULT_NUM_SEND_FRAMES = MIN_SEND_SOCK_BUFF_SIZE/udp_simple::mtu;; +#endif //a single concurrent thread for io_service seems to be the fastest static const size_t CONCURRENCY_HINT = 1; @@ -143,6 +153,12 @@ public: return get_buff_size(); } + //! handle a recv callback -> push the filled memory into the fifo + UHD_INLINE void handle_recv(void *mem, size_t len){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + _pending_recv_buffs->push_with_wait(boost::asio::buffer(mem, len)); + } + //////////////////////////////////////////////////////////////////// #ifdef USE_ASIO_ASYNC_RECV //////////////////////////////////////////////////////////////////// @@ -162,16 +178,10 @@ public: return managed_recv_buffer::sptr(); } - //! handle a recv callback -> push the filled memory into the fifo - void handle_recv(void *mem, size_t len){ - boost::this_thread::disable_interruption di; //disable because the wait can throw - _pending_recv_buffs->push_with_wait(boost::asio::buffer(mem, len)); - } - //! release a recv buffer -> start an async recv on the buffer void release(void *mem){ _socket->async_receive( - boost::asio::buffer(mem, _recv_frame_size), + boost::asio::buffer(mem, this->get_recv_frame_size()), boost::bind( &udp_zero_copy_asio_impl::handle_recv, shared_from_this(), mem, @@ -185,6 +195,7 @@ public: //////////////////////////////////////////////////////////////////// managed_recv_buffer::sptr get_recv_buff(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw + asio::mutable_buffer buff; //setup timeval for timeout timeval tv; @@ -196,34 +207,30 @@ public: FD_ZERO(&rset); FD_SET(_sock_fd, &rset); - //call select to perform timed wait - if (::select(_sock_fd+1, &rset, NULL, NULL, &tv) <= 0) - return managed_recv_buffer::sptr(); - - //grab an available buffer - asio::mutable_buffer buff; - if (not _pending_recv_buffs->pop_with_timed_wait(buff, timeout)) - return managed_recv_buffer::sptr(); - - //receive and return the buffer - return managed_recv_buffer::make_safe( - asio::buffer( - boost::asio::buffer_cast(buff), - _socket->receive(boost::asio::buffer(buff)) - ), - boost::bind( - &udp_zero_copy_asio_impl::release, - shared_from_this(), - asio::buffer_cast(buff) - ) - ); + //call select to perform timed wait and grab an available buffer with wait + //if the condition is true, call receive and return the managed buffer + if ( + ::select(_sock_fd+1, &rset, NULL, NULL, &tv) > 0 and + _pending_recv_buffs->pop_with_timed_wait(buff, timeout) + ){ + return managed_recv_buffer::make_safe( + asio::buffer( + boost::asio::buffer_cast(buff), + _socket->receive(asio::buffer(buff)) + ), + boost::bind( + &udp_zero_copy_asio_impl::release, + shared_from_this(), + asio::buffer_cast(buff) + ) + ); + } + return managed_recv_buffer::sptr(); } void release(void *mem){ boost::this_thread::disable_interruption di; //disable because the wait can throw - _pending_recv_buffs->push_with_wait( - boost::asio::buffer(mem, this->get_recv_frame_size()) - ); + handle_recv(mem, this->get_recv_frame_size()); } //////////////////////////////////////////////////////////////////// @@ -233,6 +240,12 @@ public: size_t get_num_recv_frames(void) const {return _num_recv_frames;} size_t get_recv_frame_size(void) const {return _recv_frame_size;} + //! handle a send callback -> push the emptied memory into the fifo + UHD_INLINE void handle_send(void *mem){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + _pending_send_buffs->push_with_wait(boost::asio::buffer(mem, this->get_send_frame_size())); + } + //! pop an empty send buffer off of the fifo and bind with the commit callback managed_send_buffer::sptr get_send_buff(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw @@ -249,12 +262,9 @@ public: return managed_send_buffer::sptr(); } - //! handle a send callback -> push the emptied memory into the fifo - void handle_send(void *mem){ - boost::this_thread::disable_interruption di; //disable because the wait can throw - _pending_send_buffs->push_with_wait(boost::asio::buffer(mem, _send_frame_size)); - } - + //////////////////////////////////////////////////////////////////// + #ifdef USE_ASIO_ASYNC_SEND + //////////////////////////////////////////////////////////////////// //! commit a send buffer -> start an async send on the buffer void commit(void *mem, size_t len){ _socket->async_send( @@ -266,6 +276,18 @@ public: ); } + //////////////////////////////////////////////////////////////////// + #else /*USE_ASIO_ASYNC_SEND*/ + //////////////////////////////////////////////////////////////////// + void commit(void *mem, size_t len){ + _socket->send(asio::buffer(mem, len)); + handle_send(mem); + } + + //////////////////////////////////////////////////////////////////// + #endif /*USE_ASIO_ASYNC_SEND*/ + //////////////////////////////////////////////////////////////////// + size_t get_num_send_frames(void) const {return _num_send_frames;} size_t get_send_frame_size(void) const {return _send_frame_size;} @@ -297,6 +319,13 @@ template static void resize_buff_helper( if (name == "recv") min_sock_buff_size = MIN_RECV_SOCK_BUFF_SIZE; if (name == "send") min_sock_buff_size = MIN_SEND_SOCK_BUFF_SIZE; + std::string help_message; + #if defined(UHD_PLATFORM_LINUX) + help_message = str(boost::format( + "Please run: sudo sysctl -w net.core.%smem_max=%d\n" + ) % ((name == "recv")?"r":"w") % min_sock_buff_size); + #endif /*defined(UHD_PLATFORM_LINUX)*/ + //resize the buffer if size was provided if (target_size > 0){ size_t actual_size = udp_trans->resize_buff(target_size); @@ -308,13 +337,10 @@ template static void resize_buff_helper( "Current %s sock buff size: %d bytes" ) % name % actual_size << std::endl; if (actual_size < target_size) uhd::print_warning(str(boost::format( - "The %1% buffer is smaller than the requested size.\n" - "The minimum recommended buffer size is %2% bytes.\n" - "See the transport application notes on buffer resizing.\n" - #if defined(UHD_PLATFORM_LINUX) - "Please run: sudo sysctl -w net.core.rmem_max=%2%\n" - #endif /*defined(UHD_PLATFORM_LINUX)*/ - ) % name % min_sock_buff_size)); + "The %s buffer is smaller than the requested size.\n" + "The minimum recommended buffer size is %d bytes.\n" + "See the transport application notes on buffer resizing.\n%s" + ) % name % min_sock_buff_size % help_message)); } //only enable on platforms that are happy with the large buffer resize -- cgit v1.2.3 From 1190bc5c1a7bd0946bc55373eca58ec60a100f63 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 15:52:33 -0700 Subject: usrp: added calls to get subdev and mboard canonical names --- host/include/uhd/usrp/single_usrp.hpp | 16 +++++++++++++--- host/lib/usrp/single_usrp.cpp | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 1b89a3620..bc6943478 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -57,15 +57,21 @@ public: */ virtual device::sptr get_device(void) = 0; + /******************************************************************* + * Mboard methods + ******************************************************************/ /*! * Get a printable name for this usrp. * \return a printable string */ virtual std::string get_pp_string(void) = 0; - /******************************************************************* - * Misc - ******************************************************************/ + /*! + * Get canonical name for this USRP motherboard. + * \return a string representing the name + */ + virtual std::string get_mboard_name(void) = 0; + /*! * Gets the current time in the usrp time registers. * \return a timespec representing current usrp time @@ -113,6 +119,8 @@ public: virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(void) = 0; + virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; + virtual void set_rx_rate(double rate) = 0; virtual double get_rx_rate(void) = 0; @@ -146,6 +154,8 @@ public: virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(void) = 0; + virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; + virtual void set_tx_rate(double rate) = 0; virtual double get_tx_rate(void) = 0; diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index bb4af44b8..08dc3bb1d 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -54,6 +54,9 @@ public: return _dev; } + /******************************************************************* + * Mboard methods + ******************************************************************/ std::string get_pp_string(void){ std::string buff = str(boost::format( "Single USRP:\n" @@ -101,9 +104,10 @@ public: return buff; } - /******************************************************************* - * Misc - ******************************************************************/ + std::string get_mboard_name(void){ + return _mboard()[MBOARD_PROP_NAME].as(); + } + time_spec_t get_time_now(void){ return _mboard()[MBOARD_PROP_TIME_NOW].as(); } @@ -135,6 +139,10 @@ public: return _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as(); } + std::string get_rx_subdev_name(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_NAME].as(); + } + void set_rx_rate(double rate){ _rx_dsp()[DSP_PROP_HOST_RATE] = rate; } @@ -206,6 +214,10 @@ public: return _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as(); } + std::string get_tx_subdev_name(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_NAME].as(); + } + void set_tx_rate(double rate){ _tx_dsp()[DSP_PROP_HOST_RATE] = rate; } -- cgit v1.2.3 From 58e1ca09772408d5d18ee219146fe57d2045c496 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 16:33:48 -0700 Subject: usrp: comments for set subdev spec in single usrp --- host/include/uhd/usrp/single_usrp.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'host/include') diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index bc6943478..3cd263bce 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -116,6 +116,11 @@ public: /******************************************************************* * RX methods ******************************************************************/ + /*! + * Set the RX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(void) = 0; @@ -151,6 +156,11 @@ public: /******************************************************************* * TX methods ******************************************************************/ + /*! + * Set the TX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(void) = 0; -- cgit v1.2.3 From f28c07db44694e3cce96502183c7570a386987f5 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 11 Oct 2010 18:21:11 -0700 Subject: UHD: Brought out set_rx_bandwidth for dboards with programmable rx filters. --- host/include/uhd/usrp/mimo_usrp.hpp | 2 ++ host/include/uhd/usrp/simple_usrp.hpp | 2 ++ host/include/uhd/usrp/single_usrp.hpp | 2 ++ host/lib/usrp/mimo_usrp.cpp | 4 ++++ host/lib/usrp/simple_usrp.cpp | 4 ++++ host/lib/usrp/single_usrp.cpp | 4 ++++ 6 files changed, 18 insertions(+) (limited to 'host/include') diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index 10a404059..ed40addb3 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -148,6 +148,8 @@ public: * \return the rssi in dB */ virtual float read_rssi(size_t chan) = 0; + + virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; /******************************************************************* * TX methods diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 6149f739c..6f3597ed7 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -139,6 +139,8 @@ public: virtual float read_rssi(void) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(void) = 0; + + virtual void set_rx_bandwidth(float) = 0; /******************************************************************* * TX methods diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 3cd263bce..fa6498d13 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -152,6 +152,8 @@ public: virtual float read_rssi(size_t chan = 0) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; + + virtual void set_rx_bandwidth(float bandwidth, size_t chan = 0) = 0; /******************************************************************* * TX methods diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index 9331c7fbb..5437607a6 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -225,6 +225,10 @@ public: float read_rssi(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } + + void set_rx_bandwidth(float bandwidth, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } /******************************************************************* * TX methods diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index b89b76eed..b4f34287b 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -136,6 +136,10 @@ public: dboard_iface::sptr get_rx_dboard_iface(void){ return _sdev->get_rx_dboard_iface(); } + + void set_rx_bandwidth(float bandwidth) { + return _sdev->set_rx_bandwidth(bandwidth); + } /******************************************************************* * TX methods diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 08dc3bb1d..7d053535e 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -202,6 +202,10 @@ public: dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } + + void set_rx_bandwidth(float bandwidth, size_t chan) { + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } /******************************************************************* * TX methods -- cgit v1.2.3 From 3b36c206e56b415974ed83a52a652b65f9de1add Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 11 Oct 2010 18:37:04 -0700 Subject: UHD: reordered MIMO set_rx_bandwidth arg order --- host/include/uhd/usrp/mimo_usrp.hpp | 2 +- host/lib/usrp/mimo_usrp.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index ed40addb3..bdd84a148 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -149,7 +149,7 @@ public: */ virtual float read_rssi(size_t chan) = 0; - virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; + virtual void set_rx_bandwidth(size_t chan, float bandwidth) = 0; /******************************************************************* * TX methods diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index 5437607a6..08618c288 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -226,7 +226,7 @@ public: return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } - void set_rx_bandwidth(float bandwidth, size_t chan){ + void set_rx_bandwidth(size_t chan, float bandwidth){ _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; } -- cgit v1.2.3 From c861f98c55c38250a0d87ed91f5c19b10192a4b8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 16 Oct 2010 18:07:10 -0700 Subject: usrp: created multi-usrp (multi chan, multi board), and deprecated mimo-usrp --- host/include/uhd/usrp/CMakeLists.txt | 1 + host/include/uhd/usrp/mimo_usrp.hpp | 4 +- host/include/uhd/usrp/multi_usrp.hpp | 259 +++++++++++++++++++++ host/include/uhd/usrp/single_usrp.hpp | 6 +- host/lib/usrp/CMakeLists.txt | 1 + host/lib/usrp/mimo_usrp.cpp | 6 + host/lib/usrp/multi_usrp.cpp | 422 ++++++++++++++++++++++++++++++++++ host/lib/usrp/single_usrp.cpp | 4 - 8 files changed, 694 insertions(+), 9 deletions(-) create mode 100644 host/include/uhd/usrp/multi_usrp.hpp create mode 100644 host/lib/usrp/multi_usrp.cpp (limited to 'host/include') diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index f973e401a..abddf3951 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -42,6 +42,7 @@ INSTALL(FILES simple_usrp.hpp single_usrp.hpp mimo_usrp.hpp + multi_usrp.hpp DESTINATION ${INCLUDE_DIR}/uhd/usrp ) diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index bdd84a148..7c250b2fd 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -32,12 +32,12 @@ namespace uhd{ namespace usrp{ /*! - * The MIMO USRP device class: + * The MIMO USRP device class (DEPRECATED): * A mimo usrp facilitates ease-of-use for multi-usrp scenarios. * The wrapper provides convenience functions to control the group * of underlying devices as if they consisted of a single device. */ -class UHD_API mimo_usrp : boost::noncopyable{ +class UHD_API UHD_DEPRECATED mimo_usrp : boost::noncopyable{ public: typedef boost::shared_ptr sptr; diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp new file mode 100644 index 000000000..65c7e9044 --- /dev/null +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -0,0 +1,259 @@ +// +// 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_MULTI_USRP_HPP +#define INCLUDED_UHD_USRP_MULTI_USRP_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ namespace usrp{ + +/*! + * The multi-USRP device class: + * A multi-USRP facilitates ease-of-use for multiple USRP scenarios. + * The wrapper provides convenience functions to control the group + * of underlying devices as if they consisted of a single device. + * + * A few notes about a multi-USRP configuration: + * - All boards share a common RX sample rate + * - All boards share a common TX sample rate + * - All boards share a common RX subdevice specification size + * - All boards share a common TX subdevice specification size + * - All boards must have synchronized times (see the set_time_*() calls) + * + * Example to setup channel mapping: + *
+ *
+ * //create a multi_usrp with two boards in the configuration
+ * device_addr_t dev_addr;
+ * dev_addr["addr"] = "192.168.10.2 192.168.10.3";
+ * multi_usrp::sptr dev = multi_usrp::make(dev_addr);
+ *
+ * //set the board on 10.2 to use the A RX subdevice (RX channel 0)
+ * dev->set_rx_subdev_spec(":A", 0);
+ *
+ * //set the board on 10.3 to use the B RX subdevice (RX channel 1)
+ * dev->set_rx_subdev_spec(":B", 1);
+ *
+ * //set both boards to use the AB TX subdevice (TX channels 0 and 1)
+ * dev->set_tx_subdev_spec(":AB", multi_usrp::ALL_MBOARDS);
+ *
+ * //now that all the channels are mapped, continue with configuration...
+ *
+ * 
+ */ +class UHD_API multi_usrp : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + //! A wildcard motherboard index + static const size_t ALL_MBOARDS = size_t(~0); + + /*! + * Make a new multi usrp from the device address. + * \param dev_addr the device address + * \return a new single usrp object + */ + static sptr make(const device_addr_t &dev_addr); + + /*! + * Get the underlying device object. + * This is needed to get access to the streaming API and properties. + * \return the device object within this single usrp + */ + virtual device::sptr get_device(void) = 0; + + /******************************************************************* + * Mboard methods + ******************************************************************/ + /*! + * Get a printable summary for this USRP configuration. + * \return a printable string + */ + virtual std::string get_pp_string(void) = 0; + + /*! + * Get canonical name for this USRP motherboard. + * \param mboard which motherboard to query + * \return a string representing the name + */ + virtual std::string get_mboard_name(size_t mboard) = 0; + + /*! + * Gets the current time in the usrp time registers. + * \return a timespec representing current usrp time + */ + virtual time_spec_t get_time_now(void) = 0; + + /*! + * Set the time registers on the usrp at the next pps tick. + * The values will not be latched in until the pulse occurs. + * It is recommended that the user sleep(1) after calling to ensure + * that the time registers will be in a known state prior to use. + * + * Note: Because this call sets the time on the "next" pps, + * the seconds in the time spec should be current seconds + 1. + * + * \param time_spec the time to latch into the usrp device + */ + virtual void set_time_next_pps(const time_spec_t &time_spec) = 0; + + /*! + * Synchronize the times across all motherboards in this configuration. + * Use this method to sync the times when the edge of the PPS is unknown. + * + * Ex: Host machine is not attached to serial port of GPSDO + * and can therefore not query the GPSDO for the PPS edge. + * + * This is a 3-step process, and will take at most 3 seconds to complete. + * Upon completion, the times will be synchronized to the time provided. + * + * - Step1: set the time at the next pps (potential race condition) + * - Step2: wait for the seconds to rollover to catch the pps edge + * - Step3: set the time at the next pps (synchronous for all boards) + * + * \param time_spec the time to latch into the usrp device + */ + virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0; + + /*! + * Issue a stream command to the usrp device. + * This tells the usrp to send samples into the host. + * See the documentation for stream_cmd_t for more info. + * \param stream_cmd the stream command to issue + */ + virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; + + /*! + * Set the clock configuration for the usrp device. + * This tells the usrp how to get a 10Mhz reference and PPS clock. + * See the documentation for clock_config_t for more info. + * \param clock_config the clock configuration to set + * \param mboard which motherboard to set the config + */ + virtual void set_clock_config(const clock_config_t &clock_config, size_t mboard) = 0; + + /*! + * Get the number of USRP motherboards in this configuration. + */ + virtual size_t get_num_mboards(void) = 0; + + /******************************************************************* + * RX methods + ******************************************************************/ + /*! + * Set the RX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + */ + virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t mboard) = 0; + + /*! + * Get the number of RX channels in this configuration. + * This is the number of USRPs times the number of RX channels per board, + * where the number of RX channels per board is homogeneous among all USRPs. + */ + virtual size_t get_rx_num_channels(void) = 0; + + virtual std::string get_rx_subdev_name(size_t chan) = 0; + + virtual void set_rx_rate(double rate) = 0; + virtual double get_rx_rate(void) = 0; + + virtual tune_result_t set_rx_freq(double freq, size_t chan) = 0; + virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan) = 0; + virtual double get_rx_freq(size_t chan) = 0; + virtual freq_range_t get_rx_freq_range(size_t chan) = 0; + + virtual void set_rx_gain(float gain, size_t chan) = 0; + virtual float get_rx_gain(size_t chan) = 0; + virtual gain_range_t get_rx_gain_range(size_t chan) = 0; + + virtual void set_rx_antenna(const std::string &ant, size_t chan) = 0; + virtual std::string get_rx_antenna(size_t chan) = 0; + virtual std::vector get_rx_antennas(size_t chan) = 0; + + virtual bool get_rx_lo_locked(size_t chan) = 0; + + /*! + * Read the RSSI value from a usrp device. + * Or throw if the dboard does not support an RSSI readback. + * \return the rssi in dB + */ + virtual float read_rssi(size_t chan) = 0; + + virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan) = 0; + + virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; + + /******************************************************************* + * TX methods + ******************************************************************/ + /*! + * Set the TX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + */ + virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t mboard) = 0; + + /*! + * Get the number of TX channels in this configuration. + * This is the number of USRPs times the number of TX channels per board, + * where the number of TX channels per board is homogeneous among all USRPs. + */ + virtual size_t get_tx_num_channels(void) = 0; + + virtual std::string get_tx_subdev_name(size_t chan) = 0; + + virtual void set_tx_rate(double rate) = 0; + virtual double get_tx_rate(void) = 0; + + virtual tune_result_t set_tx_freq(double freq, size_t chan) = 0; + virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan) = 0; + virtual double get_tx_freq(size_t chan) = 0; + virtual freq_range_t get_tx_freq_range(size_t chan) = 0; + + virtual void set_tx_gain(float gain, size_t chan) = 0; + virtual float get_tx_gain(size_t chan) = 0; + virtual gain_range_t get_tx_gain_range(size_t chan) = 0; + + virtual void set_tx_antenna(const std::string &ant, size_t chan) = 0; + virtual std::string get_tx_antenna(size_t chan) = 0; + virtual std::vector get_tx_antennas(size_t chan) = 0; + + virtual bool get_tx_lo_locked(size_t chan) = 0; + + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan) = 0; +}; + +}} + +#endif /* INCLUDED_UHD_USRP_MULTI_USRP_HPP */ diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index fa6498d13..2266e7f2c 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -33,8 +33,8 @@ namespace uhd{ namespace usrp{ /*! - * The single USRP device class: - * A single usrp facilitates ease-of-use for most use-case scenarios. + * The single-USRP device class: + * A single-USRP 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. * This wrapper supports multi-channel configurations per motherboard. @@ -61,7 +61,7 @@ public: * Mboard methods ******************************************************************/ /*! - * Get a printable name for this usrp. + * Get a printable summary for this USRP configuration. * \return a printable string */ virtual std::string get_pp_string(void) = 0; diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 69a190bfa..d8898caff 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -25,6 +25,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/multi_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/single_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index 08618c288..f5a80a3e6 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -347,5 +347,11 @@ private: * The Make Function **********************************************************************/ mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ + uhd::print_warning( + "The mimo USRP interface has been deprecated.\n" + "Please switch to the multi USRP interface.\n" + "#include \n" + "multi_usrp::sptr sdev = multi_usrp::make(args);\n" + ); return sptr(new mimo_usrp_impl(dev_addr)); } diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp new file mode 100644 index 000000000..d0fc5c0f6 --- /dev/null +++ b/host/lib/usrp/multi_usrp.cpp @@ -0,0 +1,422 @@ +// +// 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 +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ + double codec_rate = dsp[DSP_PROP_CODEC_RATE].as(); + return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); +} + +/*********************************************************************** + * Simple USRP Implementation + **********************************************************************/ +class multi_usrp_impl : public multi_usrp{ +public: + multi_usrp_impl(const device_addr_t &addr){ + _dev = device::make(addr); + } + + device::sptr get_device(void){ + return _dev; + } + + /******************************************************************* + * Mboard methods + ******************************************************************/ + std::string get_pp_string(void){ + std::string buff = str(boost::format( + "Multi USRP:\n" + " Device: %s\n" + ) + % (*_dev)[DEVICE_PROP_NAME].as() + ); + for (size_t m = 0; m < get_num_mboards(); m++){ + buff += str(boost::format( + " Mboard %d: %s\n" + ) % m + % _mboard(m)[MBOARD_PROP_NAME].as() + ); + } + + //----------- rx side of life ---------------------------------- + for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ + buff += str(boost::format( + " RX DSP %d: %s\n" + ) % m + % _rx_dsp(m)[DSP_PROP_NAME].as() + ); + for (; chan < (m + 1)*get_rx_subdev_spec(m).size(); chan++){ + buff += str(boost::format( + " RX Channel: %u\n" + " RX Dboard: %s\n" + " RX Subdev: %s\n" + ) % chan + % _rx_dboard(chan)[DBOARD_PROP_NAME].as() + % _rx_subdev(chan)[SUBDEV_PROP_NAME].as() + ); + } + } + + //----------- tx side of life ---------------------------------- + for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ + buff += str(boost::format( + " TX DSP %d: %s\n" + ) % m + % _tx_dsp(m)[DSP_PROP_NAME].as() + ); + for (; chan < (m + 1)*get_tx_subdev_spec(m).size(); chan++){ + buff += str(boost::format( + " TX Channel: %u\n" + " TX Dboard: %s\n" + " TX Subdev: %s\n" + ) % chan + % _tx_dboard(chan)[DBOARD_PROP_NAME].as() + % _tx_subdev(chan)[SUBDEV_PROP_NAME].as() + ); + } + } + + return buff; + } + + std::string get_mboard_name(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_NAME].as(); + } + + time_spec_t get_time_now(void){ + return _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + } + + void set_time_next_pps(const time_spec_t &time_spec){ + for (size_t m = 0; m < get_num_mboards(); m++){ + _mboard(m)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + } + } + + void set_time_unknown_pps(const time_spec_t &time_spec){ + std::cout << "Set time with unknown pps edge:" << std::endl; + std::cout << " 1) set times next pps (race condition)" << std::endl; + set_time_next_pps(time_spec); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + std::cout << " 2) catch seconds rollover at pps edge" << std::endl; + time_t last_secs = 0, curr_secs = 0; + while(curr_secs == last_secs){ + last_secs = curr_secs; + curr_secs = get_time_now().get_full_secs(); + } + + std::cout << " 3) set times next pps (synchronously)" << std::endl; + set_time_next_pps(time_spec); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + //verify that the time registers are read to be within a few RTT + for (size_t m = 1; m < get_num_mboards(); m++){ + time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as(); + if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big + uhd::print_warning(str(boost::format( + "Detected time deviation between board %d and board 0.\n" + "Board 0 time is %f seconds.\n" + "Board %d time is %f seconds.\n" + ) % m % time_0.get_real_secs() % m % time_i.get_real_secs())); + } + } + } + + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + for (size_t m = 0; m < get_num_mboards(); m++){ + _mboard(m)[MBOARD_PROP_STREAM_CMD] = stream_cmd; + } + } + + void set_clock_config(const clock_config_t &clock_config, size_t mboard){ + if (mboard != ALL_MBOARDS){ + _mboard(mboard)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + set_clock_config(clock_config, m); + } + } + + size_t get_num_mboards(void){ + return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().size(); + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_subdev_spec(const subdev_spec_t &spec, size_t mboard){ + if (mboard != ALL_MBOARDS){ + _mboard(mboard)[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + set_rx_subdev_spec(spec, m); + } + } + + subdev_spec_t get_rx_subdev_spec(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_RX_SUBDEV_SPEC].as(); + } + + size_t get_rx_num_channels(void){ + size_t nchan = get_rx_subdev_spec(0).size(); + for (size_t m = 1; m < get_num_mboards(); m++){ + if (nchan != get_rx_subdev_spec(m).size()){ + throw std::runtime_error("rx subdev spec size inconsistent across all mboards"); + } + } + return nchan; + } + + std::string get_rx_subdev_name(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_NAME].as(); + } + + void set_rx_rate(double rate){ + for (size_t m = 0; m < get_num_mboards(); m++){ + _rx_dsp(m)[DSP_PROP_HOST_RATE] = rate; + } + } + + double get_rx_rate(void){ + return _rx_dsp(0)[DSP_PROP_HOST_RATE].as(); + } + + tune_result_t set_rx_freq(double target_freq, size_t chan){ + size_t nchan = get_rx_num_channels(); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq); + } + + tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ + size_t nchan = get_rx_num_channels(); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + } + + double get_rx_freq(size_t chan){ + size_t nchan = get_rx_num_channels(); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan); + } + + freq_range_t get_rx_freq_range(size_t chan){ + size_t nchan = get_rx_num_channels(); + return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(nchan/chan)); + } + + void set_rx_gain(float gain, size_t chan){ + return _rx_gain_group(chan)->set_value(gain); + } + + float get_rx_gain(size_t chan){ + return _rx_gain_group(chan)->get_value(); + } + + gain_range_t get_rx_gain_range(size_t chan){ + return _rx_gain_group(chan)->get_range(); + } + + void set_rx_antenna(const std::string &ant, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_rx_antenna(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_rx_antennas(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + } + + bool get_rx_lo_locked(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); + } + + float read_rssi(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); + } + + dboard_iface::sptr get_rx_dboard_iface(size_t chan){ + return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); + } + + void set_rx_bandwidth(float bandwidth, size_t chan) { + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_subdev_spec(const subdev_spec_t &spec, size_t mboard){ + if (mboard != ALL_MBOARDS){ + _mboard(mboard)[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + set_tx_subdev_spec(spec, m); + } + } + + subdev_spec_t get_tx_subdev_spec(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_TX_SUBDEV_SPEC].as(); + } + + std::string get_tx_subdev_name(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_NAME].as(); + } + + size_t get_tx_num_channels(void){ + size_t nchan = get_tx_subdev_spec(0).size(); + for (size_t m = 1; m < get_num_mboards(); m++){ + if (nchan != get_tx_subdev_spec(m).size()){ + throw std::runtime_error("tx subdev spec size inconsistent across all mboards"); + } + } + return nchan; + } + + void set_tx_rate(double rate){ + for (size_t m = 0; m < get_num_mboards(); m++){ + _tx_dsp(m)[DSP_PROP_HOST_RATE] = rate; + } + } + + double get_tx_rate(void){ + return _tx_dsp(0)[DSP_PROP_HOST_RATE].as(); + } + + tune_result_t set_tx_freq(double target_freq, size_t chan){ + size_t nchan = get_tx_num_channels(); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq); + } + + tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ + size_t nchan = get_tx_num_channels(); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + } + + double get_tx_freq(size_t chan){ + size_t nchan = get_tx_num_channels(); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan); + } + + freq_range_t get_tx_freq_range(size_t chan){ + size_t nchan = get_tx_num_channels(); + return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(nchan/chan)); + } + + void set_tx_gain(float gain, size_t chan){ + return _tx_gain_group(chan)->set_value(gain); + } + + float get_tx_gain(size_t chan){ + return _tx_gain_group(chan)->get_value(); + } + + gain_range_t get_tx_gain_range(size_t chan){ + return _tx_gain_group(chan)->get_range(); + } + + void set_tx_antenna(const std::string &ant, size_t chan){ + _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_tx_antenna(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_tx_antennas(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + } + + bool get_tx_lo_locked(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); + } + + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ + return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); + } + +private: + device::sptr _dev; + wax::obj _mboard(size_t mboard){ + std::string mb_name = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().at(mboard); + return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, mb_name)]; + } + wax::obj _rx_dsp(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_RX_DSP]; + } + wax::obj _tx_dsp(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_TX_DSP]; + } + wax::obj _rx_dboard(size_t chan){ + size_t nchan = get_rx_num_channels(); + std::string db_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).db_name; + return _mboard(chan/nchan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + } + wax::obj _tx_dboard(size_t chan){ + size_t nchan = get_tx_num_channels(); + std::string db_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).db_name; + return _mboard(chan/nchan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + } + wax::obj _rx_subdev(size_t chan){ + size_t nchan = get_rx_num_channels(); + std::string sd_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + wax::obj _tx_subdev(size_t chan){ + size_t nchan = get_tx_num_channels(); + std::string sd_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + gain_group::sptr _rx_gain_group(size_t chan){ + size_t nchan = get_rx_num_channels(); + std::string sd_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } + gain_group::sptr _tx_gain_group(size_t chan){ + size_t nchan = get_tx_num_channels(); + std::string sd_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } +}; + +/*********************************************************************** + * The Make Function + **********************************************************************/ +multi_usrp::sptr multi_usrp::make(const device_addr_t &dev_addr){ + return sptr(new multi_usrp_impl(dev_addr)); +} diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 7d053535e..fba04cd60 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -46,10 +46,6 @@ public: _dev = device::make(addr); } - ~single_usrp_impl(void){ - /* NOP */ - } - device::sptr get_device(void){ return _dev; } -- cgit v1.2.3 From 847512647f10241d9ba828c5c284176d11437cb8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 18 Oct 2010 17:39:34 -0700 Subject: usrp: deleted deprecated simple and mimo wrappers, moved implementations into headers --- host/include/uhd/usrp/mimo_usrp.hpp | 343 ++++++++++++++++++++++++++++++++ host/include/uhd/usrp/simple_usrp.hpp | 214 ++++++++++++++++++++ host/lib/usrp/CMakeLists.txt | 2 - host/lib/usrp/mimo_usrp.cpp | 357 ---------------------------------- host/lib/usrp/simple_usrp.cpp | 226 --------------------- 5 files changed, 557 insertions(+), 585 deletions(-) delete mode 100644 host/lib/usrp/mimo_usrp.cpp delete mode 100644 host/lib/usrp/simple_usrp.cpp (limited to 'host/include') diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index 7c250b2fd..78833e24e 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -179,4 +179,347 @@ public: }} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ namespace usrp{ namespace /*anon*/{ + +static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ + double codec_rate = dsp[DSP_PROP_CODEC_RATE].as(); + return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); +} + +/*********************************************************************** + * MIMO USRP Implementation + **********************************************************************/ +class mimo_usrp_impl : public mimo_usrp{ +public: + mimo_usrp_impl(const device_addr_t &addr){ + _dev = device::make(addr); + + //set the clock config across all mboards (TODO set through api) + clock_config_t clock_config; + clock_config.ref_source = clock_config_t::REF_SMA; + clock_config.pps_source = clock_config_t::PPS_SMA; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + } + } + + ~mimo_usrp_impl(void){ + /* NOP */ + } + + device::sptr get_device(void){ + return _dev; + } + + std::string get_pp_string(void){ + std::string buff = str(boost::format( + "MIMO USRP:\n" + " Device: %s\n" + ) + % (*_dev)[DEVICE_PROP_NAME].as() + ); + for (size_t chan = 0; chan < get_num_channels(); chan++){ + buff += str(boost::format( + " Channel: %u\n" + " Mboard: %s\n" + " RX DSP: %s\n" + " RX Dboard: %s\n" + " RX Subdev: %s\n" + " TX DSP: %s\n" + " TX Dboard: %s\n" + " TX Subdev: %s\n" + ) % chan + % _mboard(chan)[MBOARD_PROP_NAME].as() + % _rx_dsp(chan)[DSP_PROP_NAME].as() + % _rx_dboard(chan)[DBOARD_PROP_NAME].as() + % _rx_subdev(chan)[SUBDEV_PROP_NAME].as() + % _tx_dsp(chan)[DSP_PROP_NAME].as() + % _tx_dboard(chan)[DBOARD_PROP_NAME].as() + % _tx_subdev(chan)[SUBDEV_PROP_NAME].as() + ); + } + return buff; + } + + size_t get_num_channels(void){ + return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().size(); + } + + /******************************************************************* + * Misc + ******************************************************************/ + time_spec_t get_time_now(void){ + //the time on the first mboard better be the same on all + return _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + } + + void set_time_next_pps(const time_spec_t &time_spec){ + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + } + } + + void set_time_unknown_pps(const time_spec_t &time_spec){ + std::cout << "Set time with unknown pps edge:" << std::endl; + std::cout << " 1) set times next pps (race condition)" << std::endl; + set_time_next_pps(time_spec); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + std::cout << " 2) catch seconds rollover at pps edge" << std::endl; + time_t last_secs = 0, curr_secs = 0; + while(curr_secs == last_secs){ + last_secs = curr_secs; + curr_secs = get_time_now().get_full_secs(); + } + + std::cout << " 3) set times next pps (synchronously)" << std::endl; + set_time_next_pps(time_spec); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + //verify that the time registers are read to be within a few RTT + for (size_t chan = 1; chan < get_num_channels(); chan++){ + time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as(); + if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big + uhd::print_warning(str(boost::format( + "Detected time deviation between board %d and board 0.\n" + "Board 0 time is %f seconds.\n" + "Board %d time is %f seconds.\n" + ) % chan % time_0.get_real_secs() % chan % time_i.get_real_secs())); + } + } + } + + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_STREAM_CMD] = stream_cmd; + } + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_subdev_spec(size_t chan, const subdev_spec_t &spec){ + UHD_ASSERT_THROW(spec.size() <= 1); + _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; + } + + subdev_spec_t get_rx_subdev_spec(size_t chan){ + return _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as(); + } + + void set_rx_rate_all(double rate){ + std::vector _actual_rates; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; + _actual_rates.push_back(_rx_dsp(chan)[DSP_PROP_HOST_RATE].as()); + } + _rx_rate = _actual_rates.front(); + if (std::count(_actual_rates, _rx_rate) != _actual_rates.size()) throw std::runtime_error( + "MIMO configuratio error: rx rate inconsistent across mboards" + ); + } + + double get_rx_rate_all(void){ + return _rx_rate; + } + + tune_result_t set_rx_freq(size_t chan, double target_freq){ + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq); + } + + tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); + } + + double get_rx_freq(size_t chan){ + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0); + } + + freq_range_t get_rx_freq_range(size_t chan){ + return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(chan)); + } + + void set_rx_gain(size_t chan, float gain){ + return _rx_gain_group(chan)->set_value(gain); + } + + float get_rx_gain(size_t chan){ + return _rx_gain_group(chan)->get_value(); + } + + gain_range_t get_rx_gain_range(size_t chan){ + return _rx_gain_group(chan)->get_range(); + } + + void set_rx_antenna(size_t chan, const std::string &ant){ + _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_rx_antenna(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_rx_antennas(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + } + + bool get_rx_lo_locked(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); + } + + float read_rssi(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); + } + + void set_rx_bandwidth(size_t chan, float bandwidth){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_subdev_spec(size_t chan, const subdev_spec_t &spec){ + UHD_ASSERT_THROW(spec.size() <= 1); + _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; + } + + subdev_spec_t get_tx_subdev_spec(size_t chan){ + return _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as(); + } + + void set_tx_rate_all(double rate){ + std::vector _actual_rates; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; + _actual_rates.push_back(_tx_dsp(chan)[DSP_PROP_HOST_RATE].as()); + } + _tx_rate = _actual_rates.front(); + if (std::count(_actual_rates, _tx_rate) != _actual_rates.size()) throw std::runtime_error( + "MIMO configuratio error: tx rate inconsistent across mboards" + ); + } + + double get_tx_rate_all(void){ + return _tx_rate; + } + + tune_result_t set_tx_freq(size_t chan, double target_freq){ + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq); + } + + tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); + } + + double get_tx_freq(size_t chan){ + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0); + } + + freq_range_t get_tx_freq_range(size_t chan){ + return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(chan)); + } + + void set_tx_gain(size_t chan, float gain){ + return _tx_gain_group(chan)->set_value(gain); + } + + float get_tx_gain(size_t chan){ + return _tx_gain_group(chan)->get_value(); + } + + gain_range_t get_tx_gain_range(size_t chan){ + return _tx_gain_group(chan)->get_range(); + } + + void set_tx_antenna(size_t chan, const std::string &ant){ + _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_tx_antenna(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_tx_antennas(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + } + + bool get_tx_lo_locked(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); + } + +private: + device::sptr _dev; + wax::obj _mboard(size_t chan){ + prop_names_t names = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as(); + return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, names.at(chan))]; + } + wax::obj _rx_dsp(size_t chan){ + return _mboard(chan)[MBOARD_PROP_RX_DSP]; + } + wax::obj _tx_dsp(size_t chan){ + return _mboard(chan)[MBOARD_PROP_TX_DSP]; + } + wax::obj _rx_dboard(size_t chan){ + std::string db_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().db_name; + return _mboard(chan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + } + wax::obj _tx_dboard(size_t chan){ + std::string db_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().db_name; + return _mboard(chan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + } + wax::obj _rx_subdev(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + wax::obj _tx_subdev(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + gain_group::sptr _rx_gain_group(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } + gain_group::sptr _tx_gain_group(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } + + //shadows + double _rx_rate, _tx_rate; +}; +}}} + +namespace uhd{ namespace usrp{ +/*********************************************************************** + * The Make Function + **********************************************************************/ +inline mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ + uhd::print_warning( + "The mimo USRP interface has been deprecated.\n" + "Please switch to the multi USRP interface.\n" + "#include \n" + "multi_usrp::sptr sdev = multi_usrp::make(args);\n" + ); + return sptr(new mimo_usrp_impl(dev_addr)); +} +}} + #endif /* INCLUDED_UHD_USRP_MIMO_USRP_HPP */ diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 6f3597ed7..22f4d64ba 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -171,4 +171,218 @@ public: }} +#include +#include + +namespace uhd{ namespace usrp{ namespace /*anon*/{ + +/*********************************************************************** + * Simple USRP Implementation + **********************************************************************/ +class simple_usrp_impl : public simple_usrp{ +public: + simple_usrp_impl(const device_addr_t &addr){ + _sdev = single_usrp::make(addr); + } + + ~simple_usrp_impl(void){ + /* NOP */ + } + + device::sptr get_device(void){ + return _sdev->get_device(); + } + + std::string get_pp_string(void){ + return _sdev->get_pp_string(); + } + + /******************************************************************* + * Misc + ******************************************************************/ + time_spec_t get_time_now(void){ + return _sdev->get_time_now(); + } + + void set_time_now(const time_spec_t &time_spec){ + return _sdev->set_time_now(time_spec); + } + + void set_time_next_pps(const time_spec_t &time_spec){ + return _sdev->set_time_next_pps(time_spec); + } + + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + return _sdev->issue_stream_cmd(stream_cmd); + } + + void set_clock_config(const clock_config_t &clock_config){ + return _sdev->set_clock_config(clock_config); + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_subdev_spec(const subdev_spec_t &spec){ + return _sdev->set_rx_subdev_spec(spec); + } + + subdev_spec_t get_rx_subdev_spec(void){ + return _sdev->get_rx_subdev_spec(); + } + + void set_rx_rate(double rate){ + return _sdev->set_rx_rate(rate); + } + + double get_rx_rate(void){ + return _sdev->get_rx_rate(); + } + + tune_result_t set_rx_freq(double target_freq){ + return _sdev->set_rx_freq(target_freq); + } + + tune_result_t set_rx_freq(double target_freq, double lo_off){ + return _sdev->set_rx_freq(target_freq, lo_off); + } + + double get_rx_freq(void){ + return _sdev->get_rx_freq(); + } + + freq_range_t get_rx_freq_range(void){ + return _sdev->get_rx_freq_range(); + } + + void set_rx_gain(float gain){ + return _sdev->set_rx_gain(gain); + } + + float get_rx_gain(void){ + return _sdev->get_rx_gain(); + } + + gain_range_t get_rx_gain_range(void){ + return _sdev->get_rx_gain_range(); + } + + void set_rx_antenna(const std::string &ant){ + return _sdev->set_rx_antenna(ant); + } + + std::string get_rx_antenna(void){ + return _sdev->get_rx_antenna(); + } + + std::vector get_rx_antennas(void){ + return _sdev->get_rx_antennas(); + } + + bool get_rx_lo_locked(void){ + return _sdev->get_rx_lo_locked(); + } + + float read_rssi(void){ + return _sdev->read_rssi(); + } + + dboard_iface::sptr get_rx_dboard_iface(void){ + return _sdev->get_rx_dboard_iface(); + } + + void set_rx_bandwidth(float bandwidth) { + return _sdev->set_rx_bandwidth(bandwidth); + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_subdev_spec(const subdev_spec_t &spec){ + return _sdev->set_tx_subdev_spec(spec); + } + + subdev_spec_t get_tx_subdev_spec(void){ + return _sdev->get_tx_subdev_spec(); + } + + void set_tx_rate(double rate){ + return _sdev->set_tx_rate(rate); + } + + double get_tx_rate(void){ + return _sdev->get_tx_rate(); + } + + tune_result_t set_tx_freq(double target_freq){ + return _sdev->set_tx_freq(target_freq); + } + + tune_result_t set_tx_freq(double target_freq, double lo_off){ + return _sdev->set_tx_freq(target_freq, lo_off); + } + + double get_tx_freq(void){ + return _sdev->get_tx_freq(); + } + + freq_range_t get_tx_freq_range(void){ + return _sdev->get_tx_freq_range(); + } + + void set_tx_gain(float gain){ + return _sdev->set_tx_gain(gain); + } + + float get_tx_gain(void){ + return _sdev->get_tx_gain(); + } + + gain_range_t get_tx_gain_range(void){ + return _sdev->get_tx_gain_range(); + } + + void set_tx_antenna(const std::string &ant){ + return _sdev->set_tx_antenna(ant); + } + + std::string get_tx_antenna(void){ + return _sdev->get_tx_antenna(); + } + + std::vector get_tx_antennas(void){ + return _sdev->get_tx_antennas(); + } + + bool get_tx_lo_locked(void){ + return _sdev->get_tx_lo_locked(); + } + + dboard_iface::sptr get_tx_dboard_iface(void){ + return _sdev->get_tx_dboard_iface(); + } + +private: + single_usrp::sptr _sdev; +}; + +}}} + +namespace uhd{ namespace usrp{ + +/*********************************************************************** + * The Make Function + **********************************************************************/ +inline simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ + uhd::print_warning( + "The simple USRP interface has been deprecated.\n" + "Please switch to the single USRP interface.\n" + "#include \n" + "single_usrp::sptr sdev = single_usrp::make(args);\n" + ); + return sptr(new simple_usrp_impl(dev_addr)); +} + +}} + #endif /* INCLUDED_UHD_USRP_SIMPLE_USRP_HPP */ diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 906a5ff29..eeb181e0b 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -23,10 +23,8 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_id.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/multi_usrp.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/single_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp deleted file mode 100644 index f5a80a3e6..000000000 --- a/host/lib/usrp/mimo_usrp.cpp +++ /dev/null @@ -1,357 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; - -static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ - double codec_rate = dsp[DSP_PROP_CODEC_RATE].as(); - return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); -} - -/*********************************************************************** - * MIMO USRP Implementation - **********************************************************************/ -class mimo_usrp_impl : public mimo_usrp{ -public: - mimo_usrp_impl(const device_addr_t &addr){ - _dev = device::make(addr); - - //set the clock config across all mboards (TODO set through api) - clock_config_t clock_config; - clock_config.ref_source = clock_config_t::REF_SMA; - clock_config.pps_source = clock_config_t::PPS_SMA; - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _mboard(chan)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; - } - } - - ~mimo_usrp_impl(void){ - /* NOP */ - } - - device::sptr get_device(void){ - return _dev; - } - - std::string get_pp_string(void){ - std::string buff = str(boost::format( - "MIMO USRP:\n" - " Device: %s\n" - ) - % (*_dev)[DEVICE_PROP_NAME].as() - ); - for (size_t chan = 0; chan < get_num_channels(); chan++){ - buff += str(boost::format( - " Channel: %u\n" - " Mboard: %s\n" - " RX DSP: %s\n" - " RX Dboard: %s\n" - " RX Subdev: %s\n" - " TX DSP: %s\n" - " TX Dboard: %s\n" - " TX Subdev: %s\n" - ) % chan - % _mboard(chan)[MBOARD_PROP_NAME].as() - % _rx_dsp(chan)[DSP_PROP_NAME].as() - % _rx_dboard(chan)[DBOARD_PROP_NAME].as() - % _rx_subdev(chan)[SUBDEV_PROP_NAME].as() - % _tx_dsp(chan)[DSP_PROP_NAME].as() - % _tx_dboard(chan)[DBOARD_PROP_NAME].as() - % _tx_subdev(chan)[SUBDEV_PROP_NAME].as() - ); - } - return buff; - } - - size_t get_num_channels(void){ - return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().size(); - } - - /******************************************************************* - * Misc - ******************************************************************/ - time_spec_t get_time_now(void){ - //the time on the first mboard better be the same on all - return _mboard(0)[MBOARD_PROP_TIME_NOW].as(); - } - - void set_time_next_pps(const time_spec_t &time_spec){ - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _mboard(chan)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; - } - } - - void set_time_unknown_pps(const time_spec_t &time_spec){ - std::cout << "Set time with unknown pps edge:" << std::endl; - std::cout << " 1) set times next pps (race condition)" << std::endl; - set_time_next_pps(time_spec); - boost::this_thread::sleep(boost::posix_time::seconds(1)); - - std::cout << " 2) catch seconds rollover at pps edge" << std::endl; - time_t last_secs = 0, curr_secs = 0; - while(curr_secs == last_secs){ - last_secs = curr_secs; - curr_secs = get_time_now().get_full_secs(); - } - - std::cout << " 3) set times next pps (synchronously)" << std::endl; - set_time_next_pps(time_spec); - boost::this_thread::sleep(boost::posix_time::seconds(1)); - - //verify that the time registers are read to be within a few RTT - for (size_t chan = 1; chan < get_num_channels(); chan++){ - time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); - time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as(); - if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - uhd::print_warning(str(boost::format( - "Detected time deviation between board %d and board 0.\n" - "Board 0 time is %f seconds.\n" - "Board %d time is %f seconds.\n" - ) % chan % time_0.get_real_secs() % chan % time_i.get_real_secs())); - } - } - } - - void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _mboard(chan)[MBOARD_PROP_STREAM_CMD] = stream_cmd; - } - } - - /******************************************************************* - * RX methods - ******************************************************************/ - void set_rx_subdev_spec(size_t chan, const subdev_spec_t &spec){ - UHD_ASSERT_THROW(spec.size() <= 1); - _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; - } - - subdev_spec_t get_rx_subdev_spec(size_t chan){ - return _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as(); - } - - void set_rx_rate_all(double rate){ - std::vector _actual_rates; - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; - _actual_rates.push_back(_rx_dsp(chan)[DSP_PROP_HOST_RATE].as()); - } - _rx_rate = _actual_rates.front(); - if (std::count(_actual_rates, _rx_rate) != _actual_rates.size()) throw std::runtime_error( - "MIMO configuratio error: rx rate inconsistent across mboards" - ); - } - - double get_rx_rate_all(void){ - return _rx_rate; - } - - tune_result_t set_rx_freq(size_t chan, double target_freq){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq); - } - - tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); - } - - double get_rx_freq(size_t chan){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0); - } - - freq_range_t get_rx_freq_range(size_t chan){ - return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(chan)); - } - - void set_rx_gain(size_t chan, float gain){ - return _rx_gain_group(chan)->set_value(gain); - } - - float get_rx_gain(size_t chan){ - return _rx_gain_group(chan)->get_value(); - } - - gain_range_t get_rx_gain_range(size_t chan){ - return _rx_gain_group(chan)->get_range(); - } - - void set_rx_antenna(size_t chan, const std::string &ant){ - _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; - } - - std::string get_rx_antenna(size_t chan){ - return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); - } - - std::vector get_rx_antennas(size_t chan){ - return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); - } - - bool get_rx_lo_locked(size_t chan){ - return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); - } - - float read_rssi(size_t chan){ - return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); - } - - void set_rx_bandwidth(size_t chan, float bandwidth){ - _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; - } - - /******************************************************************* - * TX methods - ******************************************************************/ - void set_tx_subdev_spec(size_t chan, const subdev_spec_t &spec){ - UHD_ASSERT_THROW(spec.size() <= 1); - _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; - } - - subdev_spec_t get_tx_subdev_spec(size_t chan){ - return _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as(); - } - - void set_tx_rate_all(double rate){ - std::vector _actual_rates; - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; - _actual_rates.push_back(_tx_dsp(chan)[DSP_PROP_HOST_RATE].as()); - } - _tx_rate = _actual_rates.front(); - if (std::count(_actual_rates, _tx_rate) != _actual_rates.size()) throw std::runtime_error( - "MIMO configuratio error: tx rate inconsistent across mboards" - ); - } - - double get_tx_rate_all(void){ - return _tx_rate; - } - - tune_result_t set_tx_freq(size_t chan, double target_freq){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq); - } - - tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); - } - - double get_tx_freq(size_t chan){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0); - } - - freq_range_t get_tx_freq_range(size_t chan){ - return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(chan)); - } - - void set_tx_gain(size_t chan, float gain){ - return _tx_gain_group(chan)->set_value(gain); - } - - float get_tx_gain(size_t chan){ - return _tx_gain_group(chan)->get_value(); - } - - gain_range_t get_tx_gain_range(size_t chan){ - return _tx_gain_group(chan)->get_range(); - } - - void set_tx_antenna(size_t chan, const std::string &ant){ - _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; - } - - std::string get_tx_antenna(size_t chan){ - return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); - } - - std::vector get_tx_antennas(size_t chan){ - return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); - } - - bool get_tx_lo_locked(size_t chan){ - return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); - } - -private: - device::sptr _dev; - wax::obj _mboard(size_t chan){ - prop_names_t names = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as(); - return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, names.at(chan))]; - } - wax::obj _rx_dsp(size_t chan){ - return _mboard(chan)[MBOARD_PROP_RX_DSP]; - } - wax::obj _tx_dsp(size_t chan){ - return _mboard(chan)[MBOARD_PROP_TX_DSP]; - } - wax::obj _rx_dboard(size_t chan){ - std::string db_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().db_name; - return _mboard(chan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; - } - wax::obj _tx_dboard(size_t chan){ - std::string db_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().db_name; - return _mboard(chan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; - } - wax::obj _rx_subdev(size_t chan){ - std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; - return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; - } - wax::obj _tx_subdev(size_t chan){ - std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; - return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; - } - gain_group::sptr _rx_gain_group(size_t chan){ - std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; - return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); - } - gain_group::sptr _tx_gain_group(size_t chan){ - std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; - return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); - } - - //shadows - double _rx_rate, _tx_rate; -}; - -/*********************************************************************** - * The Make Function - **********************************************************************/ -mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( - "The mimo USRP interface has been deprecated.\n" - "Please switch to the multi USRP interface.\n" - "#include \n" - "multi_usrp::sptr sdev = multi_usrp::make(args);\n" - ); - return sptr(new mimo_usrp_impl(dev_addr)); -} diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp deleted file mode 100644 index b4f34287b..000000000 --- a/host/lib/usrp/simple_usrp.cpp +++ /dev/null @@ -1,226 +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; -using namespace uhd::usrp; - -/*********************************************************************** - * Simple USRP Implementation - **********************************************************************/ -class simple_usrp_impl : public simple_usrp{ -public: - simple_usrp_impl(const device_addr_t &addr){ - _sdev = single_usrp::make(addr); - } - - ~simple_usrp_impl(void){ - /* NOP */ - } - - device::sptr get_device(void){ - return _sdev->get_device(); - } - - std::string get_pp_string(void){ - return _sdev->get_pp_string(); - } - - /******************************************************************* - * Misc - ******************************************************************/ - time_spec_t get_time_now(void){ - return _sdev->get_time_now(); - } - - void set_time_now(const time_spec_t &time_spec){ - return _sdev->set_time_now(time_spec); - } - - void set_time_next_pps(const time_spec_t &time_spec){ - return _sdev->set_time_next_pps(time_spec); - } - - void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - return _sdev->issue_stream_cmd(stream_cmd); - } - - void set_clock_config(const clock_config_t &clock_config){ - return _sdev->set_clock_config(clock_config); - } - - /******************************************************************* - * RX methods - ******************************************************************/ - void set_rx_subdev_spec(const subdev_spec_t &spec){ - return _sdev->set_rx_subdev_spec(spec); - } - - subdev_spec_t get_rx_subdev_spec(void){ - return _sdev->get_rx_subdev_spec(); - } - - void set_rx_rate(double rate){ - return _sdev->set_rx_rate(rate); - } - - double get_rx_rate(void){ - return _sdev->get_rx_rate(); - } - - tune_result_t set_rx_freq(double target_freq){ - return _sdev->set_rx_freq(target_freq); - } - - tune_result_t set_rx_freq(double target_freq, double lo_off){ - return _sdev->set_rx_freq(target_freq, lo_off); - } - - double get_rx_freq(void){ - return _sdev->get_rx_freq(); - } - - freq_range_t get_rx_freq_range(void){ - return _sdev->get_rx_freq_range(); - } - - void set_rx_gain(float gain){ - return _sdev->set_rx_gain(gain); - } - - float get_rx_gain(void){ - return _sdev->get_rx_gain(); - } - - gain_range_t get_rx_gain_range(void){ - return _sdev->get_rx_gain_range(); - } - - void set_rx_antenna(const std::string &ant){ - return _sdev->set_rx_antenna(ant); - } - - std::string get_rx_antenna(void){ - return _sdev->get_rx_antenna(); - } - - std::vector get_rx_antennas(void){ - return _sdev->get_rx_antennas(); - } - - bool get_rx_lo_locked(void){ - return _sdev->get_rx_lo_locked(); - } - - float read_rssi(void){ - return _sdev->read_rssi(); - } - - dboard_iface::sptr get_rx_dboard_iface(void){ - return _sdev->get_rx_dboard_iface(); - } - - void set_rx_bandwidth(float bandwidth) { - return _sdev->set_rx_bandwidth(bandwidth); - } - - /******************************************************************* - * TX methods - ******************************************************************/ - void set_tx_subdev_spec(const subdev_spec_t &spec){ - return _sdev->set_tx_subdev_spec(spec); - } - - subdev_spec_t get_tx_subdev_spec(void){ - return _sdev->get_tx_subdev_spec(); - } - - void set_tx_rate(double rate){ - return _sdev->set_tx_rate(rate); - } - - double get_tx_rate(void){ - return _sdev->get_tx_rate(); - } - - tune_result_t set_tx_freq(double target_freq){ - return _sdev->set_tx_freq(target_freq); - } - - tune_result_t set_tx_freq(double target_freq, double lo_off){ - return _sdev->set_tx_freq(target_freq, lo_off); - } - - double get_tx_freq(void){ - return _sdev->get_tx_freq(); - } - - freq_range_t get_tx_freq_range(void){ - return _sdev->get_tx_freq_range(); - } - - void set_tx_gain(float gain){ - return _sdev->set_tx_gain(gain); - } - - float get_tx_gain(void){ - return _sdev->get_tx_gain(); - } - - gain_range_t get_tx_gain_range(void){ - return _sdev->get_tx_gain_range(); - } - - void set_tx_antenna(const std::string &ant){ - return _sdev->set_tx_antenna(ant); - } - - std::string get_tx_antenna(void){ - return _sdev->get_tx_antenna(); - } - - std::vector get_tx_antennas(void){ - return _sdev->get_tx_antennas(); - } - - bool get_tx_lo_locked(void){ - return _sdev->get_tx_lo_locked(); - } - - dboard_iface::sptr get_tx_dboard_iface(void){ - return _sdev->get_tx_dboard_iface(); - } - -private: - single_usrp::sptr _sdev; -}; - -/*********************************************************************** - * The Make Function - **********************************************************************/ -simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( - "The simple USRP interface has been deprecated.\n" - "Please switch to the single USRP interface.\n" - "#include \n" - "single_usrp::sptr sdev = single_usrp::make(args);\n" - ); - return sptr(new simple_usrp_impl(dev_addr)); -} -- cgit v1.2.3 From cd05791ac1f8a844517add54f005d019b201ebcd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 01:21:34 -0700 Subject: uhd: made ticks signed in time spec, fixed full secs implementation, added unit tests --- host/include/uhd/types/time_spec.hpp | 4 +-- host/lib/types.cpp | 21 ++++++++----- host/test/CMakeLists.txt | 1 + host/test/time_spec_test.cpp | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 host/test/time_spec_test.cpp (limited to 'host/include') diff --git a/host/include/uhd/types/time_spec.hpp b/host/include/uhd/types/time_spec.hpp index 59b85f4b7..57d002d48 100644 --- a/host/include/uhd/types/time_spec.hpp +++ b/host/include/uhd/types/time_spec.hpp @@ -59,7 +59,7 @@ namespace uhd{ * \param tick_count the fractional seconds tick count * \param tick_rate the number of ticks per second */ - time_spec_t(time_t full_secs, size_t tick_count, double tick_rate); + time_spec_t(time_t full_secs, long tick_count, double tick_rate); /*! * Convert the fractional seconds to clock ticks. @@ -67,7 +67,7 @@ namespace uhd{ * \param tick_rate the number of ticks per second * \return the fractional seconds tick count */ - size_t get_tick_count(double tick_rate) const; + long get_tick_count(double tick_rate) const; /*! * Get the time as a real-valued seconds count. diff --git a/host/lib/types.cpp b/host/lib/types.cpp index f957cd83f..6aa82b012 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -124,14 +124,14 @@ time_spec_t::time_spec_t(time_t full_secs, double frac_secs): /* NOP */ } -time_spec_t::time_spec_t(time_t full_secs, size_t tick_count, double tick_rate): +time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate): _full_secs(full_secs), _frac_secs(double(tick_count)/tick_rate) { /* NOP */ } -size_t time_spec_t::get_tick_count(double tick_rate) const{ +long time_spec_t::get_tick_count(double tick_rate) const{ return boost::math::iround(this->get_frac_secs()*tick_rate); } @@ -140,7 +140,9 @@ double time_spec_t::get_real_secs(void) const{ } time_t time_spec_t::get_full_secs(void) const{ - return this->_full_secs + time_t(std::floor(this->_frac_secs)); + double intpart; + std::modf(this->_frac_secs, &intpart); + return this->_full_secs + time_t(intpart); } double time_spec_t::get_frac_secs(void) const{ @@ -160,13 +162,18 @@ time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){ } bool uhd::operator==(const time_spec_t &lhs, const time_spec_t &rhs){ - return lhs.get_full_secs() == rhs.get_full_secs() and lhs.get_frac_secs() == rhs.get_frac_secs(); + return + lhs.get_full_secs() == rhs.get_full_secs() and + lhs.get_frac_secs() == rhs.get_frac_secs() + ; } bool uhd::operator<(const time_spec_t &lhs, const time_spec_t &rhs){ - if (lhs.get_full_secs() < rhs.get_full_secs()) return true; - if (lhs.get_full_secs() > rhs.get_full_secs()) return false; - return lhs.get_frac_secs() < rhs.get_frac_secs(); + return ( + (lhs.get_full_secs() < rhs.get_full_secs()) or ( + (lhs.get_full_secs() == rhs.get_full_secs()) and + (lhs.get_frac_secs() < rhs.get_frac_secs()) + )); } /*********************************************************************** diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index c620fd641..fb075ea07 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -28,6 +28,7 @@ ADD_EXECUTABLE(main_test error_test.cpp gain_group_test.cpp subdev_spec_test.cpp + time_spec_test.cpp tune_helper_test.cpp vrt_test.cpp warning_test.cpp diff --git a/host/test/time_spec_test.cpp b/host/test/time_spec_test.cpp new file mode 100644 index 000000000..5ad782160 --- /dev/null +++ b/host/test/time_spec_test.cpp @@ -0,0 +1,61 @@ +// +// 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 + +BOOST_AUTO_TEST_CASE(test_time_spec_compare){ + std::cout << "Testing time specification compare..." << std::endl; + + BOOST_CHECK(uhd::time_spec_t(2.0) == uhd::time_spec_t(2.0)); + BOOST_CHECK(uhd::time_spec_t(2.0) > uhd::time_spec_t(1.0)); + BOOST_CHECK(uhd::time_spec_t(1.0) < uhd::time_spec_t(2.0)); + + BOOST_CHECK(uhd::time_spec_t(1.1) == uhd::time_spec_t(1.1)); + BOOST_CHECK(uhd::time_spec_t(1.1) > uhd::time_spec_t(1.0)); + BOOST_CHECK(uhd::time_spec_t(1.0) < uhd::time_spec_t(1.1)); + + BOOST_CHECK(uhd::time_spec_t(0.1) == uhd::time_spec_t(0.1)); + BOOST_CHECK(uhd::time_spec_t(0.2) > uhd::time_spec_t(0.1)); + BOOST_CHECK(uhd::time_spec_t(0.1) < uhd::time_spec_t(0.2)); +} + +#define CHECK_TS_EQUAL(lhs, rhs) \ + BOOST_CHECK_CLOSE((lhs).get_real_secs(), (rhs).get_real_secs(), 0.001) + +BOOST_AUTO_TEST_CASE(test_time_spec_arithmetic){ + std::cout << "Testing time specification arithmetic..." << std::endl; + + CHECK_TS_EQUAL(uhd::time_spec_t(2.3) + uhd::time_spec_t(1.0), uhd::time_spec_t(3.3)); + CHECK_TS_EQUAL(uhd::time_spec_t(2.3) - uhd::time_spec_t(1.0), uhd::time_spec_t(1.3)); + CHECK_TS_EQUAL(uhd::time_spec_t(1.0) + uhd::time_spec_t(2.3), uhd::time_spec_t(3.3)); + CHECK_TS_EQUAL(uhd::time_spec_t(1.0) - uhd::time_spec_t(2.3), uhd::time_spec_t(-1.3)); +} + +BOOST_AUTO_TEST_CASE(test_time_spec_parts){ + std::cout << "Testing time specification parts..." << std::endl; + + BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).get_full_secs(), 1); + BOOST_CHECK_CLOSE(uhd::time_spec_t(1.1).get_frac_secs(), 0.1, 0.001); + BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).get_tick_count(100), 10); + + BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).get_full_secs(), -1); + BOOST_CHECK_CLOSE(uhd::time_spec_t(-1.1).get_frac_secs(), -0.1, 0.001); + BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).get_tick_count(100), -10); +} -- cgit v1.2.3 From 799d5059bae77a24267cfc33b33c4af1c0de8c5b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 15:42:21 -0700 Subject: usrp: change the bandwidth param to a double (its a frequency), add set and gets for BW in the wrappers --- host/include/uhd/usrp/multi_usrp.hpp | 8 ++++++-- host/include/uhd/usrp/single_usrp.hpp | 8 ++++++-- host/lib/usrp/dboard/db_dbsrx.cpp | 18 ++++++------------ host/lib/usrp/dboard/db_xcvr2450.cpp | 20 ++++++++++---------- host/lib/usrp/multi_usrp.cpp | 20 ++++++++++++++++---- host/lib/usrp/single_usrp.cpp | 20 ++++++++++++++++---- 6 files changed, 60 insertions(+), 34 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 65c7e9044..dcec0c515 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -201,6 +201,9 @@ public: virtual bool get_rx_lo_locked(size_t chan) = 0; + virtual void set_rx_bandwidth(double bandwidth, size_t chan) = 0; + virtual double get_rx_bandwidth(size_t chan) = 0; + /*! * Read the RSSI value from a usrp device. * Or throw if the dboard does not support an RSSI readback. @@ -209,8 +212,6 @@ public: virtual float read_rssi(size_t chan) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan) = 0; - - virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; /******************************************************************* * TX methods @@ -251,6 +252,9 @@ public: virtual bool get_tx_lo_locked(size_t chan) = 0; + virtual void set_tx_bandwidth(double bandwidth, size_t chan) = 0; + virtual double get_tx_bandwidth(size_t chan) = 0; + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan) = 0; }; diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 2266e7f2c..9b2fd7ccf 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -144,6 +144,9 @@ public: virtual bool get_rx_lo_locked(size_t chan = 0) = 0; + virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; + virtual double get_rx_bandwidth(size_t chan = 0) = 0; + /*! * Read the RSSI value from a usrp device. * Or throw if the dboard does not support an RSSI readback. @@ -152,8 +155,6 @@ public: virtual float read_rssi(size_t chan = 0) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; - - virtual void set_rx_bandwidth(float bandwidth, size_t chan = 0) = 0; /******************************************************************* * TX methods @@ -186,6 +187,9 @@ public: virtual bool get_tx_lo_locked(size_t chan = 0) = 0; + virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; + virtual double get_tx_bandwidth(size_t chan = 0) = 0; + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; }; diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 99137dda3..939a79e58 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -69,7 +69,7 @@ public: private: double _lo_freq; - float _bandwidth; + double _bandwidth; uhd::dict _gains; max2118_write_regs_t _max2118_write_regs; max2118_read_regs_t _max2118_read_regs; @@ -79,7 +79,7 @@ private: void set_lo_freq(double target_freq); void set_gain(float gain, const std::string &name); - void set_bandwidth(float bandwidth); + void set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5)); @@ -482,9 +482,9 @@ void dbsrx::set_gain(float gain, const std::string &name){ /*********************************************************************** * Bandwidth Handling **********************************************************************/ -void dbsrx::set_bandwidth(float bandwidth){ +void dbsrx::set_bandwidth(double bandwidth){ //clip the input - bandwidth = std::clip(bandwidth, 4e6, 33e6); + bandwidth = std::clip(bandwidth, 4e6, 33e6); double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); @@ -494,7 +494,7 @@ void dbsrx::set_bandwidth(float bandwidth){ _max2118_write_regs.f_dac = std::clip(int((((bandwidth*_max2118_write_regs.m_divider)/ref_clock) - 4)/0.145),0,127); //determine actual bandwidth - _bandwidth = float((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac)); + _bandwidth = double((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac)); if (dbsrx_debug) std::cerr << boost::format( "DBSRX Filter Bandwidth: %f MHz, m: %d, f_dac: %d\n" @@ -565,12 +565,6 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(); return; -/* - case SUBDEV_PROP_RSSI: - val = this->get_rssi(); - return; -*/ - case SUBDEV_PROP_BANDWIDTH: val = _bandwidth; return; @@ -597,7 +591,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); + this->set_bandwidth(val.as()); return; default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 314c85a69..99f2a231c 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -102,7 +102,7 @@ public: private: double _lo_freq; - float _rx_bandwidth, _tx_bandwidth; + double _rx_bandwidth, _tx_bandwidth; uhd::dict _tx_gains, _rx_gains; std::string _tx_ant, _rx_ant; int _ad9515div; @@ -113,8 +113,8 @@ private: void set_rx_ant(const std::string &ant); void set_tx_gain(float gain, const std::string &name); void set_rx_gain(float gain, const std::string &name); - void set_rx_bandwidth(float bandwidth); - void set_tx_bandwidth(float bandwidth); + void set_rx_bandwidth(double bandwidth); + void set_tx_bandwidth(double bandwidth); void update_atr(void); void spi_reset(void); @@ -455,7 +455,7 @@ void xcvr2450::set_rx_gain(float gain, const std::string &name){ /*********************************************************************** * Bandwidth Handling **********************************************************************/ -static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(float &bandwidth){ +static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(double &bandwidth){ int reg = std::clip(boost::math::iround((bandwidth-6.0e6)/6.0e6), 1, 3); switch(reg){ @@ -472,7 +472,7 @@ static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(float UHD_THROW_INVALID_CODE_PATH(); } -static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(float &bandwidth, float requested_bandwidth){ +static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(double &bandwidth, double requested_bandwidth){ int reg = std::clip(boost::math::iround((requested_bandwidth/bandwidth)/0.05), 18, 22); switch(reg){ @@ -495,7 +495,7 @@ static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(float &ban UHD_THROW_INVALID_CODE_PATH(); } -static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(float &bandwidth){ +static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double &bandwidth){ int reg = std::clip(boost::math::iround((bandwidth-7.0e6)/1.0e6), 0, 11); switch(reg){ @@ -523,7 +523,7 @@ static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(float UHD_THROW_INVALID_CODE_PATH(); } -void xcvr2450::set_rx_bandwidth(float bandwidth){ +void xcvr2450::set_rx_bandwidth(double bandwidth){ float requested_bandwidth = bandwidth; //compute coarse low pass cutoff frequency setting @@ -543,7 +543,7 @@ void xcvr2450::set_rx_bandwidth(float bandwidth){ ) % _rx_bandwidth % (int(_max2829_regs.rx_lpf_coarse_adj)) % (int(_max2829_regs.rx_lpf_fine_adj)) << std::endl; } -void xcvr2450::set_tx_bandwidth(float bandwidth){ +void xcvr2450::set_tx_bandwidth(double bandwidth){ //compute coarse low pass cutoff frequency setting _max2829_regs.tx_lpf_coarse_adj = bandwidth_to_tx_lpf_coarse_reg(bandwidth); @@ -652,7 +652,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_rx_bandwidth(val.as()); + this->set_rx_bandwidth(val.as()); return; case SUBDEV_PROP_ENABLED: @@ -747,7 +747,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_tx_bandwidth(val.as()); + this->set_tx_bandwidth(val.as()); return; case SUBDEV_PROP_ANTENNA: diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 6df3afbf8..027530f31 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -256,6 +256,14 @@ public: return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_rx_bandwidth(double bandwidth, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_rx_bandwidth(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + float read_rssi(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } @@ -263,10 +271,6 @@ public: dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } - - void set_rx_bandwidth(float bandwidth, size_t chan) { - _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; - } /******************************************************************* * TX methods @@ -352,6 +356,14 @@ public: return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_tx_bandwidth(double bandwidth, size_t chan){ + _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_tx_bandwidth(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 7a4df3eb5..2faa1280c 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -192,6 +192,14 @@ public: return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_rx_bandwidth(double bandwidth, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_rx_bandwidth(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + float read_rssi(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } @@ -199,10 +207,6 @@ public: dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } - - void set_rx_bandwidth(float bandwidth, size_t chan) { - _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; - } /******************************************************************* * TX methods @@ -276,6 +280,14 @@ public: return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_tx_bandwidth(double bandwidth, size_t chan){ + _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_tx_bandwidth(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } -- cgit v1.2.3 From b405abf883a5b37de1468cde679644927d89abce Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 17:13:56 -0700 Subject: uhd: remove some warnings in MSVC and with typo in xcvr2450 --- host/include/uhd/config.hpp | 5 +++-- host/lib/usrp/dboard/db_xcvr2450.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index dacd3a96b..2918c2340 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -31,11 +31,12 @@ # pragma warning(disable: 4251) // class 'A' needs to have dll-interface to be used by clients of class 'B' //# pragma warning(disable: 4127) // conditional expression is constant //# pragma warning(disable: 4290) // C++ exception specification ignored except to ... -# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored +//# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored # pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ... //# pragma warning(disable: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data //# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated -# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance +//# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance +# pragma warning(disable: 4200) // nonstandard extension used : zero-sized array in struct/union #endif // define logical operators diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 99f2a231c..fb1367113 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -524,7 +524,7 @@ static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double } void xcvr2450::set_rx_bandwidth(double bandwidth){ - float requested_bandwidth = bandwidth; + double requested_bandwidth = bandwidth; //compute coarse low pass cutoff frequency setting _max2829_regs.rx_lpf_coarse_adj = bandwidth_to_rx_lpf_coarse_reg(bandwidth); -- cgit v1.2.3 From e0c48ba5cc1033cd330e2ce73ceb03740923e954 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 12:11:26 -0700 Subject: usrp: added docstrings to single and multi usrp for undocumented methods --- host/include/uhd/usrp/multi_usrp.hpp | 219 +++++++++++++++++++++++++++++++++- host/include/uhd/usrp/single_usrp.hpp | 217 ++++++++++++++++++++++++++++++++- 2 files changed, 432 insertions(+), 4 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index dcec0c515..6adba85bd 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -170,8 +170,16 @@ public: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification + * \param mboard the motherboard index 0 to M-1 */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + + /*! + * Get the RX subdevice specification. + * \param mboard the motherboard index 0 to M-1 + * \return the subdevice specification in use + */ virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t mboard) = 0; /*! @@ -181,36 +189,136 @@ public: */ virtual size_t get_rx_num_channels(void) = 0; + /*! + * Get the name of the RX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ virtual std::string get_rx_subdev_name(size_t chan) = 0; + /*! + * Set the RX sample rate across all channels. + * \param rate the rate in Sps + */ virtual void set_rx_rate(double rate) = 0; + + /*! + * Gets the RX sample rate for all channels. + * \return the rate in Sps + */ virtual double get_rx_rate(void) = 0; + /*! + * Set the RX center frequency. + * \param freq the frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_rx_freq(double freq, size_t chan) = 0; + + /*! + * Set the RX center frequency. + * \param freq the frequency in Hz + * \param lo_off an LO offset in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan) = 0; + + /*! + * Get the RX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ virtual double get_rx_freq(size_t chan) = 0; + + /*! + * Get the RX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ virtual freq_range_t get_rx_freq_range(size_t chan) = 0; + /*! + * Set the RX gain: + * Distribute among gain elements in the RX path. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_gain(float gain, size_t chan) = 0; + + /*! + * Get the RX gain: + * Summation of gain elements in the RX path. + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ virtual float get_rx_gain(size_t chan) = 0; + + /*! + * Get the RX gain range. + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ virtual gain_range_t get_rx_gain_range(size_t chan) = 0; + /*! + * Select the RX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_antenna(const std::string &ant, size_t chan) = 0; + + /*! + * Get the selected RX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ virtual std::string get_rx_antenna(size_t chan) = 0; + + /*! + * Get a list of possible RX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ virtual std::vector get_rx_antennas(size_t chan) = 0; + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ virtual bool get_rx_lo_locked(size_t chan) = 0; + /*! + * Set the RX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_bandwidth(double bandwidth, size_t chan) = 0; + + /*! + * Get the RX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ virtual double get_rx_bandwidth(size_t chan) = 0; /*! - * Read the RSSI value from a usrp device. - * Or throw if the dboard does not support an RSSI readback. + * Read the RSSI value on the RX subdevice. + * \param chan the channel index 0 to N-1 * \return the rssi in dB + * \throw exception if RSSI readback not supported */ virtual float read_rssi(size_t chan) = 0; + /*! + * Get the dboard interface object for the RX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan) = 0; /******************************************************************* @@ -221,8 +329,16 @@ public: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification + * \param mboard the motherboard index 0 to M-1 */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + + /*! + * Get the TX subdevice specification. + * \param mboard the motherboard index 0 to M-1 + * \return the subdevice specification in use + */ virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t mboard) = 0; /*! @@ -232,29 +348,128 @@ public: */ virtual size_t get_tx_num_channels(void) = 0; + /*! + * Get the name of the TX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ virtual std::string get_tx_subdev_name(size_t chan) = 0; + /*! + * Set the TX sample rate across all channels. + * \param rate the rate in Sps + */ virtual void set_tx_rate(double rate) = 0; + + /*! + * Gets the TX sample rate for all channels. + * \return the rate in Sps + */ virtual double get_tx_rate(void) = 0; + /*! + * Set the TX center frequency. + * \param freq the frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_tx_freq(double freq, size_t chan) = 0; + + /*! + * Set the TX center frequency. + * \param freq the frequency in Hz + * \param lo_off an LO offset in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan) = 0; + + /*! + * Get the TX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ virtual double get_tx_freq(size_t chan) = 0; + + /*! + * Get the TX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ virtual freq_range_t get_tx_freq_range(size_t chan) = 0; + /*! + * Set the TX gain: + * Distribute among gain elements in the TX path. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_gain(float gain, size_t chan) = 0; + + /*! + * Get the TX gain: + * Summation of gain elements in the TX path. + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ virtual float get_tx_gain(size_t chan) = 0; + + /*! + * Get the TX gain range. + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ virtual gain_range_t get_tx_gain_range(size_t chan) = 0; + /*! + * Select the TX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_antenna(const std::string &ant, size_t chan) = 0; + + /*! + * Get the selected TX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ virtual std::string get_tx_antenna(size_t chan) = 0; + + /*! + * Get a list of possible TX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ virtual std::vector get_tx_antennas(size_t chan) = 0; + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ virtual bool get_tx_lo_locked(size_t chan) = 0; + /*! + * Set the TX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_bandwidth(double bandwidth, size_t chan) = 0; + + /*! + * Get the TX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ virtual double get_tx_bandwidth(size_t chan) = 0; + /*! + * Get the dboard interface object for the TX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan) = 0; }; diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 9b2fd7ccf..74a978f05 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -120,40 +120,147 @@ public: * Set the RX subdevice specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; + + /*! + * Get the RX subdevice specification. + * \return the subdevice specification in use + */ virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(void) = 0; + /*! + * Get the name of the RX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; + /*! + * Set the RX sample rate across all channels. + * \param rate the rate in Sps + */ virtual void set_rx_rate(double rate) = 0; + + /*! + * Gets the RX sample rate for all channels. + * \return the rate in Sps + */ virtual double get_rx_rate(void) = 0; + /*! + * Set the RX center frequency. + * \param freq the frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_rx_freq(double freq, size_t chan = 0) = 0; + + /*! + * Set the RX center frequency. + * \param freq the frequency in Hz + * \param lo_off an LO offset in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan = 0) = 0; + + /*! + * Get the RX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ virtual double get_rx_freq(size_t chan = 0) = 0; + + /*! + * Get the RX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ virtual freq_range_t get_rx_freq_range(size_t chan = 0) = 0; + /*! + * Set the RX gain: + * Distribute among gain elements in the RX path. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_gain(float gain, size_t chan = 0) = 0; + + /*! + * Get the RX gain: + * Summation of gain elements in the RX path. + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ virtual float get_rx_gain(size_t chan = 0) = 0; + + /*! + * Get the RX gain range. + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ virtual gain_range_t get_rx_gain_range(size_t chan = 0) = 0; + /*! + * Select the RX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_antenna(const std::string &ant, size_t chan = 0) = 0; + + /*! + * Get the selected RX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ virtual std::string get_rx_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible RX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ virtual std::vector get_rx_antennas(size_t chan = 0) = 0; + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ virtual bool get_rx_lo_locked(size_t chan = 0) = 0; + /*! + * Set the RX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; + + /*! + * Get the RX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ virtual double get_rx_bandwidth(size_t chan = 0) = 0; /*! - * Read the RSSI value from a usrp device. - * Or throw if the dboard does not support an RSSI readback. + * Read the RSSI value on the RX subdevice. + * \param chan the channel index 0 to N-1 * \return the rssi in dB + * \throw exception if RSSI readback not supported */ virtual float read_rssi(size_t chan = 0) = 0; + /*! + * Get the dboard interface object for the RX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; /******************************************************************* @@ -163,33 +270,139 @@ public: * Set the TX subdevice specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; + + /*! + * Get the TX subdevice specification. + * \return the subdevice specification in use + */ virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(void) = 0; + /*! + * Get the name of the TX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; + /*! + * Set the TX sample rate across all channels. + * \param rate the rate in Sps + */ virtual void set_tx_rate(double rate) = 0; + + /*! + * Gets the TX sample rate for all channels. + * \return the rate in Sps + */ virtual double get_tx_rate(void) = 0; + /*! + * Set the TX center frequency. + * \param freq the frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_tx_freq(double freq, size_t chan = 0) = 0; + + /*! + * Set the TX center frequency. + * \param freq the frequency in Hz + * \param lo_off an LO offset in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan = 0) = 0; + + /*! + * Get the TX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ virtual double get_tx_freq(size_t chan = 0) = 0; + + /*! + * Get the TX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ virtual freq_range_t get_tx_freq_range(size_t chan = 0) = 0; + /*! + * Set the TX gain: + * Distribute among gain elements in the TX path. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_gain(float gain, size_t chan = 0) = 0; + + /*! + * Get the TX gain: + * Summation of gain elements in the TX path. + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ virtual float get_tx_gain(size_t chan = 0) = 0; + + /*! + * Get the TX gain range. + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ virtual gain_range_t get_tx_gain_range(size_t chan = 0) = 0; + /*! + * Select the TX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_antenna(const std::string &ant, size_t chan = 0) = 0; + + /*! + * Get the selected TX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ virtual std::string get_tx_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible TX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ virtual std::vector get_tx_antennas(size_t chan = 0) = 0; + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ virtual bool get_tx_lo_locked(size_t chan = 0) = 0; + /*! + * Set the TX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; + + /*! + * Get the TX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ virtual double get_tx_bandwidth(size_t chan = 0) = 0; + /*! + * Get the dboard interface object for the TX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; }; -- cgit v1.2.3 From 26aef3bae98aae5364deb40a62b52ba65b9aa16a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 15:32:41 -0700 Subject: uhd: added name parameter to gain group, get range, set/get value by name --- host/include/uhd/utils/gain_group.hpp | 43 +++++++++++++++++++++++++++-------- host/lib/usrp/misc_utils.cpp | 4 ++-- host/lib/utils/gain_group.cpp | 26 +++++++++++++++++---- host/test/gain_group_test.cpp | 4 ++-- 4 files changed, 59 insertions(+), 18 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/utils/gain_group.hpp b/host/include/uhd/utils/gain_group.hpp index 3955dfa9a..c863248ce 100644 --- a/host/include/uhd/utils/gain_group.hpp +++ b/host/include/uhd/utils/gain_group.hpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include namespace uhd{ @@ -40,36 +42,57 @@ public: typedef boost::shared_ptr sptr; /*! - * Get the overall gain range for this group. + * Get the gain range for the gain element specified by name. + * For an empty name, get the overall gain range for this group. * Overall step is defined as the minimum step size. + * \param name name of the gain element (optional) * \return a gain range with overall min, max, step */ - virtual gain_range_t get_range(void) = 0; + virtual gain_range_t get_range(const std::string &name = "") = 0; /*! - * Get the overall gain value for this group. - * \return a summation of all the gain values + * Get the gain value for the gain element specified by name. + * For an empty name, get the overall gain value for this group. + * \param name name of the gain element (optional) + * \return a gain value of the element or all elements */ - virtual float get_value(void) = 0; + virtual float get_value(const std::string &name = "") = 0; /*! - * Set the overall gain value for this group. + * Set the gain value for the gain element specified by name. + * For an empty name, set the overall gain value for this group. * The power will be distributed across individual gain elements. * The semantics of how to do this are determined by the priority. - * \param gain the gain to set across the group + * \param gain the gain to set for the lement or across the group + * \param name name of the gain element (optional) */ - virtual void set_value(float gain) = 0; + virtual void set_value(float gain, const std::string &name = "") = 0; /*! - * Register a set of gain functions into this group. + * Get a list of names of registered gain elements. + * The names are in the order that they were registered. + * \return a vector of gain name strings + */ + virtual const std::vector get_names(void) = 0; + + /*! + * Register a set of gain functions into this group: + * + * The name should be a unique and non-empty name. + * Othwerwise, the implementation will rename it. + * * Priority determines how power will be distributed * with higher priorities getting the power first, * and lower priorities getting the remainder power. + * + * \param name the name of the gain element * \param gain_fcns the set of gain functions * \param priority the priority of the gain element */ virtual void register_fcns( - const gain_fcns_t &gain_fcns, size_t priority = 0 + const std::string &name, + const gain_fcns_t &gain_fcns, + size_t priority = 0 ) = 0; /*! diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 05308baba..499a6ebfb 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -95,7 +95,7 @@ gain_group::sptr usrp::make_gain_group( fcns.get_range = boost::bind(&get_subdev_gain_range, subdev, name); fcns.get_value = boost::bind(&get_subdev_gain, subdev, name); fcns.set_value = boost::bind(&set_subdev_gain, subdev, name, _1); - gg->register_fcns(fcns, subdev_gain_priority); + gg->register_fcns(name, fcns, subdev_gain_priority); } //add all the codec gains last (antenna to dsp order) BOOST_FOREACH(const std::string &name, codec[CODEC_PROP_GAIN_NAMES].as()){ @@ -119,7 +119,7 @@ gain_group::sptr usrp::make_gain_group( fcns.set_value = boost::bind(&set_codec_gain_q, codec, name, _1); break; } - gg->register_fcns(fcns, codec_gain_priority); + gg->register_fcns(name, fcns, codec_gain_priority); } return gg; } diff --git a/host/lib/utils/gain_group.cpp b/host/lib/utils/gain_group.cpp index 078fe56b2..54146726a 100644 --- a/host/lib/utils/gain_group.cpp +++ b/host/lib/utils/gain_group.cpp @@ -63,7 +63,9 @@ public: /*NOP*/ } - gain_range_t get_range(void){ + gain_range_t get_range(const std::string &name){ + if (not name.empty()) return _name_to_fcns[name].get_range(); + float overall_min = 0, overall_max = 0, overall_step = 0; BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){ const gain_range_t range = fcns.get_range(); @@ -76,7 +78,9 @@ public: return gain_range_t(overall_min, overall_max, overall_step); } - float get_value(void){ + float get_value(const std::string &name){ + if (not name.empty()) return _name_to_fcns[name].get_value(); + float overall_gain = 0; BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){ overall_gain += fcns.get_value(); @@ -84,7 +88,9 @@ public: return overall_gain; } - void set_value(float gain){ + void set_value(float gain, const std::string &name){ + if (not name.empty()) return _name_to_fcns[name].set_value(gain); + std::vector all_fcns = get_all_fcns(); if (all_fcns.size() == 0) return; //nothing to set! @@ -140,10 +146,21 @@ public: } } + const std::vector get_names(void){ + return _name_to_fcns.keys(); + } + void register_fcns( - const gain_fcns_t &gain_fcns, size_t priority + const std::string &name, + const gain_fcns_t &gain_fcns, + size_t priority ){ + if (name.empty() or _name_to_fcns.has_key(name)){ + //ensure the name name is unique and non-empty + return register_fcns(name + "_", gain_fcns, priority); + } _registry[priority].push_back(gain_fcns); + _name_to_fcns[name] = gain_fcns; } private: @@ -158,6 +175,7 @@ private: } uhd::dict > _registry; + uhd::dict _name_to_fcns; }; /*********************************************************************** diff --git a/host/test/gain_group_test.cpp b/host/test/gain_group_test.cpp index 761372e5a..555ccaed3 100644 --- a/host/test/gain_group_test.cpp +++ b/host/test/gain_group_test.cpp @@ -81,12 +81,12 @@ static gain_group::sptr get_gain_group(size_t pri1 = 0, size_t pri2 = 0){ gain_fcns.get_range = boost::bind(&gain_element1::get_range, &g1); gain_fcns.get_value = boost::bind(&gain_element1::get_value, &g1); gain_fcns.set_value = boost::bind(&gain_element1::set_value, &g1, _1); - gg->register_fcns(gain_fcns, pri1); + gg->register_fcns("g1", gain_fcns, pri1); gain_fcns.get_range = boost::bind(&gain_element2::get_range, &g2); gain_fcns.get_value = boost::bind(&gain_element2::get_value, &g2); gain_fcns.set_value = boost::bind(&gain_element2::set_value, &g2, _1); - gg->register_fcns(gain_fcns, pri2); + gg->register_fcns("g2", gain_fcns, pri2); return gg; } -- cgit v1.2.3 From 8e341caadf19db645635e3e7e1a26e6b00e64c70 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 16:20:36 -0700 Subject: usrp: added gain element access by gain name to multi and single wrappers --- host/include/uhd/usrp/multi_usrp.hpp | 59 +++++++++++++++++++------- host/include/uhd/usrp/single_usrp.hpp | 79 ++++++++++++++++++++++++++++------- host/lib/usrp/multi_usrp.cpp | 34 +++++++++------ host/lib/usrp/single_usrp.cpp | 34 +++++++++------ 4 files changed, 150 insertions(+), 56 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 6adba85bd..70901fc31 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -73,6 +73,9 @@ public: //! A wildcard motherboard index static const size_t ALL_MBOARDS = size_t(~0); + //! A wildcard gain element name + static const std::string ALL_GAINS; + /*! * Make a new multi usrp from the device address. * \param dev_addr the device address @@ -240,27 +243,39 @@ public: virtual freq_range_t get_rx_freq_range(size_t chan) = 0; /*! - * Set the RX gain: - * Distribute among gain elements in the RX path. + * Set the RX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. * \param gain the gain in dB + * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_rx_gain(float gain, size_t chan) = 0; + virtual void set_rx_gain(float gain, const std::string &name, size_t chan) = 0; /*! - * Get the RX gain: - * Summation of gain elements in the RX path. + * Get the RX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_rx_gain(size_t chan) = 0; + virtual float get_rx_gain(const std::string &name, size_t chan) = 0; /*! - * Get the RX gain range. + * Get the RX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_rx_gain_range(size_t chan) = 0; + virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan) = 0; + + /*! + * Get the names of the gain elements in the RX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector get_rx_gain_names(size_t chan) = 0; /*! * Select the RX antenna on the subdevice. @@ -399,27 +414,39 @@ public: virtual freq_range_t get_tx_freq_range(size_t chan) = 0; /*! - * Set the TX gain: - * Distribute among gain elements in the TX path. + * Set the TX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. * \param gain the gain in dB + * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_tx_gain(float gain, size_t chan) = 0; + virtual void set_tx_gain(float gain, const std::string &name, size_t chan) = 0; /*! - * Get the TX gain: - * Summation of gain elements in the TX path. + * Get the TX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_tx_gain(size_t chan) = 0; + virtual float get_tx_gain(const std::string &name, size_t chan) = 0; /*! - * Get the TX gain range. + * Get the TX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_tx_gain_range(size_t chan) = 0; + virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan) = 0; + + /*! + * Get the names of the gain elements in the TX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector get_tx_gain_names(size_t chan) = 0; /*! * Select the TX antenna on the subdevice. diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 74a978f05..09bf9c84d 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -43,6 +43,9 @@ class UHD_API single_usrp : boost::noncopyable{ public: typedef boost::shared_ptr sptr; + //! A wildcard gain element name + static const std::string ALL_GAINS; + /*! * Make a new single usrp from the device address. * \param dev_addr the device address @@ -182,27 +185,49 @@ public: virtual freq_range_t get_rx_freq_range(size_t chan = 0) = 0; /*! - * Set the RX gain: - * Distribute among gain elements in the RX path. + * Set the RX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. * \param gain the gain in dB + * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_rx_gain(float gain, size_t chan = 0) = 0; + virtual void set_rx_gain( + float gain, + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; /*! - * Get the RX gain: - * Summation of gain elements in the RX path. + * Get the RX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_rx_gain(size_t chan = 0) = 0; + virtual float get_rx_gain( + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; /*! - * Get the RX gain range. + * Get the RX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_rx_gain_range(size_t chan = 0) = 0; + virtual gain_range_t get_rx_gain_range( + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; + + /*! + * Get the names of the gain elements in the RX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector get_rx_gain_names(size_t chan = 0) = 0; /*! * Select the RX antenna on the subdevice. @@ -332,27 +357,49 @@ public: virtual freq_range_t get_tx_freq_range(size_t chan = 0) = 0; /*! - * Set the TX gain: - * Distribute among gain elements in the TX path. + * Set the TX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. * \param gain the gain in dB + * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_tx_gain(float gain, size_t chan = 0) = 0; + virtual void set_tx_gain( + float gain, + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; /*! - * Get the TX gain: - * Summation of gain elements in the TX path. + * Get the TX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_tx_gain(size_t chan = 0) = 0; + virtual float get_tx_gain( + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; /*! - * Get the TX gain range. + * Get the TX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_tx_gain_range(size_t chan = 0) = 0; + virtual gain_range_t get_tx_gain_range( + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; + + /*! + * Get the names of the gain elements in the TX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector get_tx_gain_names(size_t chan = 0) = 0; /*! * Select the TX antenna on the subdevice. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 027530f31..443b91594 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -35,6 +35,8 @@ using namespace uhd; using namespace uhd::usrp; +const std::string multi_usrp::ALL_GAINS = ""; + /*********************************************************************** * Simple USRP Implementation **********************************************************************/ @@ -228,16 +230,20 @@ public: return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(chan/rx_cpm())); } - void set_rx_gain(float gain, size_t chan){ - return _rx_gain_group(chan)->set_value(gain); + void set_rx_gain(float gain, const std::string &name, size_t chan){ + return _rx_gain_group(chan)->set_value(gain, name); + } + + float get_rx_gain(const std::string &name, size_t chan){ + return _rx_gain_group(chan)->get_value(name); } - float get_rx_gain(size_t chan){ - return _rx_gain_group(chan)->get_value(); + gain_range_t get_rx_gain_range(const std::string &name, size_t chan){ + return _rx_gain_group(chan)->get_range(name); } - gain_range_t get_rx_gain_range(size_t chan){ - return _rx_gain_group(chan)->get_range(); + std::vector get_rx_gain_names(size_t chan){ + return _rx_gain_group(chan)->get_names(); } void set_rx_antenna(const std::string &ant, size_t chan){ @@ -328,16 +334,20 @@ public: return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(chan/tx_cpm())); } - void set_tx_gain(float gain, size_t chan){ - return _tx_gain_group(chan)->set_value(gain); + void set_tx_gain(float gain, const std::string &name, size_t chan){ + return _tx_gain_group(chan)->set_value(gain, name); + } + + float get_tx_gain(const std::string &name, size_t chan){ + return _tx_gain_group(chan)->get_value(name); } - float get_tx_gain(size_t chan){ - return _tx_gain_group(chan)->get_value(); + gain_range_t get_tx_gain_range(const std::string &name, size_t chan){ + return _tx_gain_group(chan)->get_range(name); } - gain_range_t get_tx_gain_range(size_t chan){ - return _tx_gain_group(chan)->get_range(); + std::vector get_tx_gain_names(size_t chan){ + return _tx_gain_group(chan)->get_names(); } void set_tx_antenna(const std::string &ant, size_t chan){ diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 2faa1280c..5e57849b8 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -33,6 +33,8 @@ using namespace uhd; using namespace uhd::usrp; +const std::string single_usrp::ALL_GAINS = ""; + /*********************************************************************** * Simple USRP Implementation **********************************************************************/ @@ -164,16 +166,20 @@ public: return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp()); } - void set_rx_gain(float gain, size_t chan){ - return _rx_gain_group(chan)->set_value(gain); + void set_rx_gain(float gain, const std::string &name, size_t chan){ + return _rx_gain_group(chan)->set_value(gain, name); + } + + float get_rx_gain(const std::string &name, size_t chan){ + return _rx_gain_group(chan)->get_value(name); } - float get_rx_gain(size_t chan){ - return _rx_gain_group(chan)->get_value(); + gain_range_t get_rx_gain_range(const std::string &name, size_t chan){ + return _rx_gain_group(chan)->get_range(name); } - gain_range_t get_rx_gain_range(size_t chan){ - return _rx_gain_group(chan)->get_range(); + std::vector get_rx_gain_names(size_t chan){ + return _rx_gain_group(chan)->get_names(); } void set_rx_antenna(const std::string &ant, size_t chan){ @@ -252,16 +258,20 @@ public: return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp()); } - void set_tx_gain(float gain, size_t chan){ - return _tx_gain_group(chan)->set_value(gain); + void set_tx_gain(float gain, const std::string &name, size_t chan){ + return _tx_gain_group(chan)->set_value(gain, name); + } + + float get_tx_gain(const std::string &name, size_t chan){ + return _tx_gain_group(chan)->get_value(name); } - float get_tx_gain(size_t chan){ - return _tx_gain_group(chan)->get_value(); + gain_range_t get_tx_gain_range(const std::string &name, size_t chan){ + return _tx_gain_group(chan)->get_range(name); } - gain_range_t get_tx_gain_range(size_t chan){ - return _tx_gain_group(chan)->get_range(); + std::vector get_tx_gain_names(size_t chan){ + return _tx_gain_group(chan)->get_names(); } void set_tx_antenna(const std::string &ant, size_t chan){ -- cgit v1.2.3 From d96b2e7587962c43c1db895b3340f9d868cbd704 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 17:41:59 -0700 Subject: usrp: use the dboard id to prefix the subdev gain group names --- host/include/uhd/usrp/dboard_id.hpp | 6 ++++++ host/include/uhd/usrp/misc_utils.hpp | 3 +++ host/lib/usrp/dboard/db_dbsrx.cpp | 9 ++------- host/lib/usrp/dboard/db_rfx.cpp | 12 ++++++------ host/lib/usrp/dboard/db_tvrx.cpp | 2 +- host/lib/usrp/dboard_manager.cpp | 11 ++++++----- host/lib/usrp/misc_utils.cpp | 7 +++++-- host/lib/usrp/usrp1/codec_impl.cpp | 24 +++++++++++++----------- host/lib/usrp/usrp1/dboard_impl.cpp | 2 ++ host/lib/usrp/usrp2/dboard_impl.cpp | 2 ++ 10 files changed, 46 insertions(+), 32 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 4c45e4334..1fda8182e 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -66,6 +66,12 @@ namespace uhd{ namespace usrp{ */ std::string to_string(void) const; + /*! + * Get the dboard id represented as a canonical name. + * \return the canonical string representation + */ + std::string to_cname(void) const; + /*! * Get the pretty print representation of this dboard id. * \return a string with the dboard name and id number diff --git a/host/include/uhd/usrp/misc_utils.hpp b/host/include/uhd/usrp/misc_utils.hpp index 2af9f5b40..37860a1a5 100644 --- a/host/include/uhd/usrp/misc_utils.hpp +++ b/host/include/uhd/usrp/misc_utils.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -35,11 +36,13 @@ namespace uhd{ namespace usrp{ /*! * Create a gain group that represents the subdevice and its codec. + * \param dboard_id the dboard id for this subdevice * \param subdev the object with subdevice properties * \param codec the object with codec properties * \param gain_group_policy the policy to use */ UHD_API gain_group::sptr make_gain_group( + const dboard_id_t &dboard_id, wax::obj subdev, wax::obj codec, gain_group_policy_t gain_group_policy ); diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 939a79e58..0b8b4db83 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -162,15 +162,10 @@ static dboard_base::sptr make_dbsrx(dboard_base::ctor_args_t args){ return dboard_base::sptr(new dbsrx(args)); } -//dbid for USRP2 version UHD_STATIC_BLOCK(reg_dbsrx_dboard){ - //register the factory function for the rx dbid + //register the factory function for the rx dbid (others version) dboard_manager::register_dboard(0x000D, &make_dbsrx, "DBSRX"); -} - -//dbid for USRP1 version -UHD_STATIC_BLOCK(reg_dbsrx_on_usrp1_dboard){ - //register the factory function for the rx dbid + //register the factory function for the rx dbid (USRP1 version) dboard_manager::register_dboard(0x0002, &make_dbsrx, "DBSRX"); } diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index cfc34381e..3c24d90db 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -152,12 +152,12 @@ static dboard_base::sptr make_rfx_flex2400(dboard_base::ctor_args_t args){ } UHD_STATIC_BLOCK(reg_rfx_dboards){ - dboard_manager::register_dboard(0x0024, 0x0028, &make_rfx_flex400, "Flex 400 MIMO B"); - dboard_manager::register_dboard(0x0025, 0x0029, &make_rfx_flex900, "Flex 900 MIMO B"); - dboard_manager::register_dboard(0x0034, 0x0035, &make_rfx_flex1800, "Flex 1800 MIMO B"); - dboard_manager::register_dboard(0x0026, 0x002a, &make_rfx_flex1200, "Flex 1200 MIMO B"); - dboard_manager::register_dboard(0x002c, 0x002d, &make_rfx_flex2200, "Flex 2200 MIMO B"); - dboard_manager::register_dboard(0x0027, 0x002b, &make_rfx_flex2400, "Flex 2400 MIMO B"); + dboard_manager::register_dboard(0x0024, 0x0028, &make_rfx_flex400, "RFX400"); + dboard_manager::register_dboard(0x0025, 0x0029, &make_rfx_flex900, "RFX900"); + dboard_manager::register_dboard(0x0034, 0x0035, &make_rfx_flex1800, "RFX1800"); + dboard_manager::register_dboard(0x0026, 0x002a, &make_rfx_flex1200, "RFX1200"); + dboard_manager::register_dboard(0x002c, 0x002d, &make_rfx_flex2200, "RFX2200"); + dboard_manager::register_dboard(0x0027, 0x002b, &make_rfx_flex2400, "RFX2400"); } /*********************************************************************** diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 10be8d1c3..d39dc3bf8 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -179,7 +179,7 @@ static dboard_base::sptr make_tvrx(dboard_base::ctor_args_t args){ UHD_STATIC_BLOCK(reg_tvrx_dboard){ //register the factory function for the rx dbid - dboard_manager::register_dboard(0x0040, &make_tvrx, "tvrx"); + dboard_manager::register_dboard(0x0040, &make_tvrx, "TVRX"); } /*********************************************************************** diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 78daa1b4d..d7e7943c4 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -77,12 +77,13 @@ void dboard_manager::register_dboard( get_xcvr_id_to_id_map()[tx_dboard_id] = rx_dboard_id; } +std::string dboard_id_t::to_cname(void) const{ + if (not get_id_to_args_map().has_key(*this)) return "Unknown"; + return get_id_to_args_map()[*this].get<1>(); +} + std::string dboard_id_t::to_pp_string(void) const{ - std::string name = "unknown"; - if (get_id_to_args_map().has_key(*this)){ - name = get_id_to_args_map()[*this].get<1>(); - } - return str(boost::format("%s (%s)") % name % this->to_string()); + return str(boost::format("%s (%s)") % this->to_cname() % this->to_string()); } /*********************************************************************** diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 499a6ebfb..e95af45bd 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -80,6 +80,7 @@ static void set_subdev_gain(wax::obj subdev, const std::string &name, float gain * gain group factory function for usrp **********************************************************************/ gain_group::sptr usrp::make_gain_group( + const dboard_id_t &dboard_id, wax::obj subdev, wax::obj codec, gain_group_policy_t gain_group_policy ){ @@ -87,6 +88,8 @@ gain_group::sptr usrp::make_gain_group( const size_t codec_gain_priority = (gain_group_policy == GAIN_GROUP_POLICY_RX)? (subdev_gain_priority - 1): //RX policy, codec gains fill last (lower priority) (subdev_gain_priority + 1); //TX policy, codec gains fill first (higher priority) + const std::string subdev_prefix = dboard_id.to_cname() + " "; + const std::string codec_prefix = (gain_group_policy == GAIN_GROUP_POLICY_RX)? "ADC " : "DAC "; gain_group::sptr gg = gain_group::make(); gain_fcns_t fcns; @@ -95,7 +98,7 @@ gain_group::sptr usrp::make_gain_group( fcns.get_range = boost::bind(&get_subdev_gain_range, subdev, name); fcns.get_value = boost::bind(&get_subdev_gain, subdev, name); fcns.set_value = boost::bind(&set_subdev_gain, subdev, name, _1); - gg->register_fcns(name, fcns, subdev_gain_priority); + gg->register_fcns(subdev_prefix+name, fcns, subdev_gain_priority); } //add all the codec gains last (antenna to dsp order) BOOST_FOREACH(const std::string &name, codec[CODEC_PROP_GAIN_NAMES].as()){ @@ -119,7 +122,7 @@ gain_group::sptr usrp::make_gain_group( fcns.set_value = boost::bind(&set_codec_gain_q, codec, name, _1); break; } - gg->register_fcns(name, fcns, codec_gain_priority); + gg->register_fcns(codec_prefix+name, fcns, codec_gain_priority); } return gg; } diff --git a/host/lib/usrp/usrp1/codec_impl.cpp b/host/lib/usrp/usrp1/codec_impl.cpp index 1756c1ed4..db53be53e 100644 --- a/host/lib/usrp/usrp1/codec_impl.cpp +++ b/host/lib/usrp/usrp1/codec_impl.cpp @@ -45,7 +45,7 @@ void usrp1_impl::codec_init(void) /*********************************************************************** * RX Codec Properties **********************************************************************/ -static const std::string ad9862_pga_gain_name = "ad9862 pga"; +static const std::string adc_pga_gain_name = "PGA"; void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { @@ -62,21 +62,21 @@ void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t return; case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(1, ad9862_pga_gain_name); + val = prop_names_t(1, adc_pga_gain_name); return; case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = usrp1_codec_ctrl::rx_pga_gain_range; return; case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('A'); return; case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('B'); return; @@ -91,12 +91,12 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ //handle the set request conditioned on the key switch(key.as()) { case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'A'); return; case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'B'); return; @@ -107,6 +107,8 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ /*********************************************************************** * TX Codec Properties **********************************************************************/ +static const std::string dac_pga_gain_name = "PGA"; + void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); @@ -122,17 +124,17 @@ void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t return; case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(1, ad9862_pga_gain_name); + val = prop_names_t(1, dac_pga_gain_name); return; case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); val = usrp1_codec_ctrl::tx_pga_gain_range; return; case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_tx_pga_gain(); return; @@ -148,7 +150,7 @@ void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ switch(key.as()){ case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); _codec_ctrls[dboard_slot]->set_tx_pga_gain(val.as()); return; diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index 3a8480e1b..2a2762a82 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -124,6 +124,7 @@ void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _rx_db_eeproms[dboard_slot].id, _dboard_managers[dboard_slot]->get_rx_subdev(key.name), _rx_codec_proxies[dboard_slot]->get_link(), GAIN_GROUP_POLICY_RX @@ -188,6 +189,7 @@ void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _tx_db_eeproms[dboard_slot].id, _dboard_managers[dboard_slot]->get_tx_subdev(key.name), _tx_codec_proxies[dboard_slot]->get_link(), GAIN_GROUP_POLICY_TX diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index a462b93c2..540c9fefb 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -89,6 +89,7 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _rx_db_eeprom.id, _dboard_manager->get_rx_subdev(key.name), _rx_codec_proxy->get_link(), GAIN_GROUP_POLICY_RX @@ -145,6 +146,7 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _tx_db_eeprom.id, _dboard_manager->get_tx_subdev(key.name), _tx_codec_proxy->get_link(), GAIN_GROUP_POLICY_TX -- cgit v1.2.3 From 318d62a179806cec20b5adb4f2aad58ecc5a330e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 18:16:34 -0700 Subject: usrp: convenience wrappers for dealing with overall gains --- host/include/uhd/usrp/multi_usrp.hpp | 30 +++++++++++++++++ host/include/uhd/usrp/single_usrp.hpp | 62 ++++++++++++++++++++--------------- 2 files changed, 66 insertions(+), 26 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 70901fc31..2f71f80b1 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -251,6 +251,11 @@ public: */ virtual void set_rx_gain(float gain, const std::string &name, size_t chan) = 0; + //! A convenience wrapper for setting overall RX gain + void set_rx_gain(float gain, size_t chan){ + return this->set_rx_gain(gain, ALL_GAINS, chan); + } + /*! * Get the RX gain value for the specified gain element. * For an empty name, sum across all gain elements. @@ -260,6 +265,11 @@ public: */ virtual float get_rx_gain(const std::string &name, size_t chan) = 0; + //! A convenience wrapper for getting overall RX gain + float get_rx_gain(size_t chan){ + return this->get_rx_gain(ALL_GAINS, chan); + } + /*! * Get the RX gain range for the specified gain element. * For an empty name, calculate the overall gain range. @@ -269,6 +279,11 @@ public: */ virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan) = 0; + //! A convenience wrapper for getting overall RX gain range + gain_range_t get_rx_gain_range(size_t chan){ + return this->get_rx_gain_range(ALL_GAINS, chan); + } + /*! * Get the names of the gain elements in the RX chain. * Gain elements are ordered from antenna to FPGA. @@ -422,6 +437,11 @@ public: */ virtual void set_tx_gain(float gain, const std::string &name, size_t chan) = 0; + //! A convenience wrapper for setting overall TX gain + void set_tx_gain(float gain, size_t chan){ + return this->set_tx_gain(gain, ALL_GAINS, chan); + } + /*! * Get the TX gain value for the specified gain element. * For an empty name, sum across all gain elements. @@ -431,6 +451,11 @@ public: */ virtual float get_tx_gain(const std::string &name, size_t chan) = 0; + //! A convenience wrapper for getting overall TX gain + float get_tx_gain(size_t chan){ + return this->get_tx_gain(ALL_GAINS, chan); + } + /*! * Get the TX gain range for the specified gain element. * For an empty name, calculate the overall gain range. @@ -440,6 +465,11 @@ public: */ virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan) = 0; + //! A convenience wrapper for getting overall TX gain range + gain_range_t get_tx_gain_range(size_t chan){ + return this->get_tx_gain_range(ALL_GAINS, chan); + } + /*! * Get the names of the gain elements in the TX chain. * Gain elements are ordered from antenna to FPGA. diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 09bf9c84d..a34f92cee 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -191,11 +191,12 @@ public: * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_rx_gain( - float gain, - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual void set_rx_gain(float gain, const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for setting overall RX gain + void set_rx_gain(float gain, size_t chan = 0){ + return this->set_rx_gain(gain, ALL_GAINS, chan); + } /*! * Get the RX gain value for the specified gain element. @@ -204,10 +205,12 @@ public: * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_rx_gain( - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual float get_rx_gain(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall RX gain + float get_rx_gain(size_t chan = 0){ + return this->get_rx_gain(ALL_GAINS, chan); + } /*! * Get the RX gain range for the specified gain element. @@ -216,10 +219,12 @@ public: * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_rx_gain_range( - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall RX gain range + gain_range_t get_rx_gain_range(size_t chan = 0){ + return this->get_rx_gain_range(ALL_GAINS, chan); + } /*! * Get the names of the gain elements in the RX chain. @@ -363,11 +368,12 @@ public: * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_tx_gain( - float gain, - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual void set_tx_gain(float gain, const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for setting overall TX gain + void set_tx_gain(float gain, size_t chan = 0){ + return this->set_tx_gain(gain, ALL_GAINS, chan); + } /*! * Get the TX gain value for the specified gain element. @@ -376,10 +382,12 @@ public: * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_tx_gain( - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual float get_tx_gain(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall TX gain + float get_tx_gain(size_t chan = 0){ + return this->get_tx_gain(ALL_GAINS, chan); + } /*! * Get the TX gain range for the specified gain element. @@ -388,10 +396,12 @@ public: * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_tx_gain_range( - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall TX gain range + gain_range_t get_tx_gain_range(size_t chan = 0){ + return this->get_tx_gain_range(ALL_GAINS, chan); + } /*! * Get the names of the gain elements in the TX chain. -- cgit v1.2.3 From e2f76bddae7845024056b479658651c6da2b0f4d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 21 Oct 2010 09:43:35 -0700 Subject: usrp: remove irrelevant copied comment from single usrp --- host/include/uhd/usrp/single_usrp.hpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index a34f92cee..a068fbed8 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -123,7 +123,6 @@ public: * Set the RX subdevice specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. - * The subdev spec must be the same size across all motherboards. * \param spec the new subdevice specification */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; @@ -300,7 +299,6 @@ public: * Set the TX subdevice specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. - * The subdev spec must be the same size across all motherboards. * \param spec the new subdevice specification */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; -- cgit v1.2.3 From db0e3e574e9058ad51cacea91ccc42f0baed95fa Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 21 Oct 2010 22:26:53 -0400 Subject: usrp_e: Add driver compatibility ioctl to header file. --- host/apps/omap_debug/usrp_e.h | 3 +++ host/include/linux/usrp_e.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'host/include') diff --git a/host/apps/omap_debug/usrp_e.h b/host/apps/omap_debug/usrp_e.h index fd38027d4..f96706c4a 100644 --- a/host/apps/omap_debug/usrp_e.h +++ b/host/apps/omap_debug/usrp_e.h @@ -41,6 +41,9 @@ struct usrp_e_ctl32 { #define UE_SPI_PUSH_FALL UE_SPI_CTRL_TXNEG #define UE_SPI_LATCH_RISE 0 #define UE_SPI_LATCH_FALL UE_SPI_CTRL_RXNEG +#define USRP_E_GET_COMPAT_NUMBER _IO(USRP_E_IOC_MAGIC, 0x28) + +#define USRP_E_COMPAT_NUMBER 1 struct usrp_e_spi { __u8 readback; diff --git a/host/include/linux/usrp_e.h b/host/include/linux/usrp_e.h index cb62d940d..4c6a5dd89 100644 --- a/host/include/linux/usrp_e.h +++ b/host/include/linux/usrp_e.h @@ -65,6 +65,9 @@ struct usrp_e_i2c { #define USRP_E_I2C_READ _IOWR(USRP_E_IOC_MAGIC, 0x25, struct usrp_e_i2c) #define USRP_E_I2C_WRITE _IOW(USRP_E_IOC_MAGIC, 0x26, struct usrp_e_i2c) #define USRP_E_GET_RB_INFO _IOR(USRP_E_IOC_MAGIC, 0x27, struct usrp_e_ring_buffer_size_t) +#define USRP_E_GET_COMPAT_NUMBER _IO(USRP_E_IOC_MAGIC, 0x28) + +#define USRP_E_COMPAT_NUMBER 1 /* Flag defines */ #define RB_USER (1<<0) -- cgit v1.2.3 From 359c4e16b2d2748a97ce33073c64502a7f190aa6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 13:41:40 -0700 Subject: uhd: created tune request struct and implemented more fine grained tuning calls --- host/include/uhd/types/CMakeLists.txt | 1 + host/include/uhd/types/tune_request.hpp | 97 ++++++++++++++++++++++ host/include/uhd/usrp/mimo_usrp.hpp | 16 ++-- host/include/uhd/usrp/multi_usrp.hpp | 31 +++---- host/include/uhd/usrp/simple_usrp.hpp | 16 ++-- host/include/uhd/usrp/single_usrp.hpp | 31 +++---- host/include/uhd/usrp/tune_helper.hpp | 31 ++----- host/lib/types.cpp | 20 +++++ host/lib/usrp/multi_usrp.cpp | 24 ++---- host/lib/usrp/single_usrp.cpp | 24 ++---- host/lib/usrp/tune_helper.cpp | 138 ++++++++++++++++++-------------- 11 files changed, 247 insertions(+), 182 deletions(-) create mode 100644 host/include/uhd/types/tune_request.hpp (limited to 'host/include') diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index dbce21c98..661dd2d39 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -28,6 +28,7 @@ INSTALL(FILES serial.hpp stream_cmd.hpp time_spec.hpp + tune_request.hpp tune_result.hpp DESTINATION ${INCLUDE_DIR}/uhd/types ) diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp new file mode 100644 index 000000000..f80d2cb15 --- /dev/null +++ b/host/include/uhd/types/tune_request.hpp @@ -0,0 +1,97 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP +#define INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP + +#include + +namespace uhd{ + + /*! + * A tune request instructs the implementation how to tune the RF chain. + * The policies can be used to select automatic tuning or + * fined control over the daughterboard IF and DSP tuning. + * Not all combinations of policies are applicable. + * Convenience constructors are supplied for most use cases. + */ + struct UHD_API tune_request_t{ + /*! + * Make a new tune request for a particular center frequency. + * Use an automatic policy for the intermediate and DSP frequency + * to tune the chain as close as possible to the target frequency. + * \param target_freq the target frequency in Hz + */ + tune_request_t(double target_freq = 0); + + /*! + * Make a new tune request for a particular center frequency. + * Use a manual policy for the intermediate frequency, + * and an automatic policy for the DSP frequency, + * to tune the chain as close as possible to the target frequency. + * \param target_freq the target frequency in Hz + * \param lo_off the LO offset frequency in Hz + */ + tune_request_t(double target_freq, double lo_off); + + /*! + * Policy types for tune arguments: + * - None: do not set this argument, use current setting + * - Auto: automatically determine the argument's value + * - Manual: use the argument's value for the setting + */ + enum policy_t { + POLICY_NONE = 'N', + POLICY_AUTO = 'A', + POLICY_MANUAL = 'M' + }; + + /*! + * The target frequency of the overall chain in Hz. + * Use when one of the policies is set to automatic. + */ + double target_freq; + + /*! + * The policy for the intermediate frequency. + * Automatic behavior: the target frequency + default LO offset. + */ + policy_t inter_freq_policy; + + /*! + * The intermediate frequency in Hz. + * Set when the policy is set to manual. + */ + double inter_freq; + + /*! + * The policy for the DSP frequency. + * Automatic behavior: the difference between the target and IF. + */ + policy_t dsp_freq_policy; + + /*! + * The DSP frequency in Hz. + * Set when the policy is set to manual. + */ + double dsp_freq; + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP */ diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index 78833e24e..b5acf84e1 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -127,7 +127,7 @@ public: virtual double get_rx_rate_all(void) = 0; virtual tune_result_t set_rx_freq(size_t chan, double freq) = 0; - virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0; + //virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0; virtual double get_rx_freq(size_t chan) = 0; virtual freq_range_t get_rx_freq_range(size_t chan) = 0; @@ -161,7 +161,7 @@ public: virtual double get_tx_rate_all(void) = 0; virtual tune_result_t set_tx_freq(size_t chan, double freq) = 0; - virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0; + //virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0; virtual double get_tx_freq(size_t chan) = 0; virtual freq_range_t get_tx_freq_range(size_t chan) = 0; @@ -345,9 +345,9 @@ public: return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq); } - tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); - } + //tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ + // return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); + //} double get_rx_freq(size_t chan){ return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0); @@ -425,9 +425,9 @@ public: return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq); } - tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); - } + //tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ + // return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); + //} double get_tx_freq(size_t chan){ return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0); diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 2f71f80b1..5380d177d 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -213,20 +214,13 @@ public: /*! * Set the RX center frequency. - * \param freq the frequency in Hz + * \param tune_request tune request instructions * \param chan the channel index 0 to N-1 * \return a tune result object */ - virtual tune_result_t set_rx_freq(double freq, size_t chan) = 0; - - /*! - * Set the RX center frequency. - * \param freq the frequency in Hz - * \param lo_off an LO offset in Hz - * \param chan the channel index 0 to N-1 - * \return a tune result object - */ - virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan) = 0; + virtual tune_result_t set_rx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; /*! * Get the RX center frequency. @@ -399,20 +393,13 @@ public: /*! * Set the TX center frequency. - * \param freq the frequency in Hz - * \param chan the channel index 0 to N-1 - * \return a tune result object - */ - virtual tune_result_t set_tx_freq(double freq, size_t chan) = 0; - - /*! - * Set the TX center frequency. - * \param freq the frequency in Hz - * \param lo_off an LO offset in Hz + * \param tune_request tune request instructions * \param chan the channel index 0 to N-1 * \return a tune result object */ - virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan) = 0; + virtual tune_result_t set_tx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; /*! * Get the TX center frequency. diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 22f4d64ba..59fd9bb09 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -117,7 +117,7 @@ public: virtual double get_rx_rate(void) = 0; virtual tune_result_t set_rx_freq(double freq) = 0; - virtual tune_result_t set_rx_freq(double freq, double lo_off) = 0; + //virtual tune_result_t set_rx_freq(double freq, double lo_off) = 0; virtual double get_rx_freq(void) = 0; virtual freq_range_t get_rx_freq_range(void) = 0; @@ -152,7 +152,7 @@ public: virtual double get_tx_rate(void) = 0; virtual tune_result_t set_tx_freq(double freq) = 0; - virtual tune_result_t set_tx_freq(double freq, double lo_off) = 0; + //virtual tune_result_t set_tx_freq(double freq, double lo_off) = 0; virtual double get_tx_freq(void) = 0; virtual freq_range_t get_tx_freq_range(void) = 0; @@ -243,9 +243,9 @@ public: return _sdev->set_rx_freq(target_freq); } - tune_result_t set_rx_freq(double target_freq, double lo_off){ - return _sdev->set_rx_freq(target_freq, lo_off); - } + //tune_result_t set_rx_freq(double target_freq, double lo_off){ + // return _sdev->set_rx_freq(target_freq, lo_off); + //} double get_rx_freq(void){ return _sdev->get_rx_freq(); @@ -318,9 +318,9 @@ public: return _sdev->set_tx_freq(target_freq); } - tune_result_t set_tx_freq(double target_freq, double lo_off){ - return _sdev->set_tx_freq(target_freq, lo_off); - } + //tune_result_t set_tx_freq(double target_freq, double lo_off){ + // return _sdev->set_tx_freq(target_freq, lo_off); + //} double get_tx_freq(void){ return _sdev->get_tx_freq(); diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index a068fbed8..26303fe10 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -154,20 +155,13 @@ public: /*! * Set the RX center frequency. - * \param freq the frequency in Hz + * \param tune_request tune request instructions * \param chan the channel index 0 to N-1 * \return a tune result object */ - virtual tune_result_t set_rx_freq(double freq, size_t chan = 0) = 0; - - /*! - * Set the RX center frequency. - * \param freq the frequency in Hz - * \param lo_off an LO offset in Hz - * \param chan the channel index 0 to N-1 - * \return a tune result object - */ - virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan = 0) = 0; + virtual tune_result_t set_rx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; /*! * Get the RX center frequency. @@ -330,20 +324,13 @@ public: /*! * Set the TX center frequency. - * \param freq the frequency in Hz - * \param chan the channel index 0 to N-1 - * \return a tune result object - */ - virtual tune_result_t set_tx_freq(double freq, size_t chan = 0) = 0; - - /*! - * Set the TX center frequency. - * \param freq the frequency in Hz - * \param lo_off an LO offset in Hz + * \param tune_request tune request instructions * \param chan the channel index 0 to N-1 * \return a tune result object */ - virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan = 0) = 0; + virtual tune_result_t set_tx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; /*! * Get the TX center frequency. diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp index ec133fa08..db12241c1 100644 --- a/host/include/uhd/usrp/tune_helper.hpp +++ b/host/include/uhd/usrp/tune_helper.hpp @@ -20,6 +20,7 @@ #include #include +#include #include namespace uhd{ namespace usrp{ @@ -32,23 +33,12 @@ namespace uhd{ namespace usrp{ * \param subdev the dboard subdevice object with properties * \param ddc the mboard dsp object with properties * \param chan the channel of the dsp to tune - * \param target_freq the desired center frequency - * \param lo_offset an offset for the subdevice IF from center + * \param tune_request tune request instructions * \return a tune result struct */ UHD_API tune_result_t tune_rx_subdev_and_dsp( wax::obj subdev, wax::obj ddc, size_t chan, - double target_freq, double lo_offset - ); - - /*! - * Tune a rx chain to the desired frequency: - * Same as the above, except the LO offset - * is calculated based on the subdevice and BW. - */ - UHD_API tune_result_t tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, - size_t chan, double target_freq + const tune_request_t &tune_request ); /*! @@ -70,23 +60,12 @@ namespace uhd{ namespace usrp{ * \param subdev the dboard subdevice object with properties * \param duc the mboard dsp object with properties * \param chan the channel of the dsp to tune - * \param target_freq the desired center frequency - * \param lo_offset an offset for the subdevice IF from center + * \param tune_request tune request instructions * \return a tune result struct */ UHD_API tune_result_t tune_tx_subdev_and_dsp( wax::obj subdev, wax::obj duc, size_t chan, - double target_freq, double lo_offset - ); - - /*! - * Tune a tx chain to the desired frequency: - * Same as the above, except the LO offset - * is calculated based on the subdevice and BW. - */ - UHD_API tune_result_t tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, - size_t chan, double target_freq + const tune_request_t &tune_request ); /*! diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 6aa82b012..a8062b6ae 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -57,6 +58,25 @@ freq_range_t::freq_range_t(double min, double max): /* NOP */ } +/*********************************************************************** + * tune request + **********************************************************************/ +tune_request_t::tune_request_t(double target_freq): + target_freq(target_freq), + inter_freq_policy(POLICY_AUTO), + dsp_freq_policy(POLICY_AUTO) +{ + /* NOP */ +} + +tune_request_t::tune_request_t(double target_freq, double lo_off): + target_freq(target_freq + lo_off), + inter_freq_policy(POLICY_MANUAL), + dsp_freq_policy(POLICY_AUTO) +{ + /* NOP */ +} + /*********************************************************************** * tune result **********************************************************************/ diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 443b91594..8b82502ba 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -210,15 +210,9 @@ public: return _rx_dsp(0)[DSP_PROP_HOST_RATE].as(); } - tune_result_t set_rx_freq(double target_freq, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), target_freq); - do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); - return r; - } - - tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), target_freq, lo_off); - do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); + tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), tune_request); + do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX"); return r; } @@ -314,15 +308,9 @@ public: return _tx_dsp(0)[DSP_PROP_HOST_RATE].as(); } - tune_result_t set_tx_freq(double target_freq, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), target_freq); - do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); - return r; - } - - tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), target_freq, lo_off); - do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); + tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), tune_request); + do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX"); return r; } diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 5e57849b8..a0456d1f0 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -146,15 +146,9 @@ public: return _rx_dsp()[DSP_PROP_HOST_RATE].as(); } - tune_result_t set_rx_freq(double target_freq, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq); - do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); - return r; - } - - tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq, lo_off); - do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); + tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, tune_request); + do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX"); return r; } @@ -238,15 +232,9 @@ public: return _tx_dsp()[DSP_PROP_HOST_RATE].as(); } - tune_result_t set_tx_freq(double target_freq, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq); - do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); - return r; - } - - tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq, lo_off); - do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); + tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, tune_request); + do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX"); return r; } diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index 7633c67f2..8c57cc428 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -28,55 +28,97 @@ using namespace uhd::usrp; /*********************************************************************** * Tune Helper Functions **********************************************************************/ -static tune_result_t tune_xx_subdev_and_dxc( +static tune_result_t tune_xx_subdev_and_dsp( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dxc, size_t chan, - double target_freq, double lo_offset + wax::obj subdev, wax::obj dsp, size_t chan, + const tune_request_t &tune_request ){ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; - std::string freq_name = dxc[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); - wax::obj dxc_freq_proxy = dxc[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)]; - double dxc_sample_rate = dxc[DSP_PROP_CODEC_RATE].as(); + std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); + wax::obj dsp_freq_proxy = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)]; + double dsp_sample_rate = dsp[DSP_PROP_CODEC_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 = subdev_freq_proxy.as(); - - //perform the correction correction for dxc rates outside of nyquist - double delta_freq = std::fmod(target_freq - actual_inter_freq, dxc_sample_rate); - bool outside_of_nyquist = std::abs(delta_freq) > dxc_sample_rate/2.0; - double target_dxc_freq = (outside_of_nyquist)? - boost::math::sign(delta_freq)*dxc_sample_rate - delta_freq : -delta_freq; + //------------------------------------------------------------------ + //-- calculate the LO offset, only used with automatic policy + //------------------------------------------------------------------ + double lo_offset = 0.0; + if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ + //if the local oscillator will be in the passband, use an offset + //TODO make this nicer, use bandwidth property to clip bounds + lo_offset = 2.0*dsp[DSP_PROP_HOST_RATE].as(); + } - //invert the sign on the dxc freq given the following conditions - if (unit == dboard_iface::UNIT_TX) target_dxc_freq *= -1.0; + //------------------------------------------------------------------ + //-- set the intermediate frequency depending upon the IF policy + //------------------------------------------------------------------ + double target_inter_freq = 0.0; + switch (tune_request.inter_freq_policy){ + case tune_request_t::POLICY_AUTO: + target_inter_freq = tune_request.target_freq + lo_offset; + subdev_freq_proxy = target_inter_freq; + break; + + case tune_request_t::POLICY_MANUAL: + target_inter_freq = tune_request.inter_freq; + subdev_freq_proxy = target_inter_freq; + break; + + case tune_request_t::POLICY_NONE: break; //does not set + } + double actual_inter_freq = subdev_freq_proxy.as(); - dxc_freq_proxy = target_dxc_freq; - double actual_dxc_freq = dxc_freq_proxy.as(); + //------------------------------------------------------------------ + //-- calculate the dsp freq, only used with automatic policy + //------------------------------------------------------------------ + double delta_freq = std::fmod(target_inter_freq - actual_inter_freq, dsp_sample_rate); + bool outside_of_nyquist = std::abs(delta_freq) > dsp_sample_rate/2.0; + double target_dsp_freq = (outside_of_nyquist)? + boost::math::sign(delta_freq)*dsp_sample_rate - delta_freq : -delta_freq; + + //invert the sign on the dsp freq given the following conditions + if (unit == dboard_iface::UNIT_TX) target_dsp_freq *= -1.0; + + //------------------------------------------------------------------ + //-- set the dsp frequency depending upon the dsp frequency policy + //------------------------------------------------------------------ + switch (tune_request.dsp_freq_policy){ + case tune_request_t::POLICY_AUTO: + dsp_freq_proxy = target_dsp_freq; + break; + + case tune_request_t::POLICY_MANUAL: + target_dsp_freq = tune_request.dsp_freq; + dsp_freq_proxy = target_dsp_freq; + break; + + case tune_request_t::POLICY_NONE: break; //does not set + } + double actual_dsp_freq = dsp_freq_proxy.as(); - //load and return the tune result + //------------------------------------------------------------------ + //-- load and return the tune result + //------------------------------------------------------------------ tune_result_t tune_result; tune_result.target_inter_freq = target_inter_freq; tune_result.actual_inter_freq = actual_inter_freq; - tune_result.target_dsp_freq = target_dxc_freq; - tune_result.actual_dsp_freq = actual_dxc_freq; + tune_result.target_dsp_freq = target_dsp_freq; + tune_result.actual_dsp_freq = actual_dsp_freq; return tune_result; } -static double derive_freq_from_xx_subdev_and_dxc( +static double derive_freq_from_xx_subdev_and_dsp( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dxc, size_t chan + wax::obj subdev, wax::obj dsp, size_t chan ){ //extract actual dsp and IF frequencies double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as(); - std::string freq_name = dxc[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); - double actual_dxc_freq = dxc[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as(); + std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); + double actual_dsp_freq = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as(); - //invert the sign on the dxc freq given the following conditions - if (unit == dboard_iface::UNIT_TX) actual_dxc_freq *= -1.0; + //invert the sign on the dsp freq given the following conditions + if (unit == dboard_iface::UNIT_TX) actual_dsp_freq *= -1.0; - return actual_inter_freq - actual_dxc_freq; + return actual_inter_freq - actual_dsp_freq; } /*********************************************************************** @@ -84,27 +126,15 @@ static double derive_freq_from_xx_subdev_and_dxc( **********************************************************************/ tune_result_t usrp::tune_rx_subdev_and_dsp( wax::obj subdev, wax::obj ddc, size_t chan, - double target_freq, double lo_offset -){ - return tune_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, chan, target_freq, lo_offset); -} - -tune_result_t usrp::tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, - size_t chan, double target_freq + const tune_request_t &tune_request ){ - double lo_offset = 0.0; - //if the local oscillator will be in the passband, use an offset - if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ - lo_offset = 2.0*ddc[DSP_PROP_HOST_RATE].as(); - } - return tune_rx_subdev_and_dsp(subdev, ddc, chan, target_freq, lo_offset); + return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan, tune_request); } double usrp::derive_freq_from_rx_subdev_and_dsp( wax::obj subdev, wax::obj ddc, size_t chan ){ - return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, chan); + return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan); } /*********************************************************************** @@ -112,25 +142,13 @@ double usrp::derive_freq_from_rx_subdev_and_dsp( **********************************************************************/ tune_result_t usrp::tune_tx_subdev_and_dsp( wax::obj subdev, wax::obj duc, size_t chan, - double target_freq, double lo_offset + const tune_request_t &tune_request ){ - return tune_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, chan, target_freq, lo_offset); -} - -tune_result_t usrp::tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, - size_t chan, double target_freq -){ - double lo_offset = 0.0; - //if the local oscillator will be in the passband, use an offset - if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ - lo_offset = 2.0*duc[DSP_PROP_HOST_RATE].as(); - } - return tune_tx_subdev_and_dsp(subdev, duc, chan, target_freq, lo_offset); + return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan, tune_request); } double usrp::derive_freq_from_tx_subdev_and_dsp( wax::obj subdev, wax::obj duc, size_t chan ){ - return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, chan); + return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan); } -- cgit v1.2.3 From 01f670e81c615a16fb5a931d3842f92b56cc6c09 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 18:09:48 -0700 Subject: uhd: doxygen comments, moved enum comments, added to metadata for all entities --- host/include/uhd/types/metadata.hpp | 76 ++++++++++++++++----------------- host/include/uhd/types/tune_request.hpp | 12 +++--- 2 files changed, 43 insertions(+), 45 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 65952941c..3f250d13e 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -19,7 +19,6 @@ #define INCLUDED_UHD_TYPES_METADATA_HPP #include -#include #include namespace uhd{ @@ -30,58 +29,59 @@ namespace uhd{ * The receive routines will convert IF data headers into metadata. */ struct UHD_API rx_metadata_t{ - /*! - * Time specification: - * Set from timestamps on incoming data when provided. - */ + //! Has time specification? bool has_time_spec; + + //! Time of the first sample. time_spec_t time_spec; /*! - * Fragmentation flag and offset: + * Fragmentation flag: * Similar to IPv4 fragmentation: http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly * More fragments is true when the input buffer has insufficient size to fit * an entire received packet. More fragments will be false for the last fragment. - * The fragment offset is the sample number at the start of the receive buffer. - * For non-fragmented receives, the fragment offset should always be zero. */ bool more_fragments; - size_t fragment_offset; /*! - * Burst flags: - * Start of burst will be true for the first packet in the chain. - * End of burst will be true for the last packet in the chain. + * Fragmentation offset: + * The fragment offset is the sample number at the start of the receive buffer. + * For non-fragmented receives, the fragment offset should always be zero. */ + size_t fragment_offset; + + //! Start of burst will be true for the first packet in the chain. bool start_of_burst; + + //! End of burst will be true for the last packet in the chain. bool end_of_burst; /*! - * Error conditions: - * - none: no error associated with this metadata - * - timeout: no packet received, underlying code timed-out - * - late command: a stream command was issued in the past - * - broken chain: expected another stream command - * - overflow: an internal receive buffer has filled - * - bad packet: the buffer was unrecognizable as a vrt packet + * The error condition on a receive call. * * Note: When an overrun occurs in continuous streaming mode, * the device will continue to send samples to the host. * For other streaming modes, streaming will discontinue * until the user issues a new stream command. * - * Note: The metadata fields have meaning for the following error codes: + * The metadata fields have meaning for the following error codes: * - none * - late command * - broken chain * - overflow */ enum error_code_t { + //! No error associated with this metadata. ERROR_CODE_NONE = 0x0, + //! No packet received, implementation timed-out. ERROR_CODE_TIMEOUT = 0x1, + //! A stream command was issued in the past. ERROR_CODE_LATE_COMMAND = 0x2, + //! Expected another stream command. ERROR_CODE_BROKEN_CHAIN = 0x4, + //! An internal receive buffer has filled. ERROR_CODE_OVERFLOW = 0x8, + //! The packet could not be parsed. ERROR_CODE_BAD_PACKET = 0xf } error_code; }; @@ -93,19 +93,19 @@ namespace uhd{ */ struct UHD_API tx_metadata_t{ /*! - * Time specification: - * Set has time spec to false to perform a send "now". - * Or, set to true, and fill in time spec for a send "at". + * Has time specification? + * - Set false to send immediately. + * - Set true to send at the time specified by time spec. */ bool has_time_spec; + + //! When to send the first sample. time_spec_t time_spec; - /*! - * Burst flags: - * Set start of burst to true for the first packet in the chain. - * Set end of burst to true for the last packet in the chain. - */ + //! Set start of burst to true for the first packet in the chain. bool start_of_burst; + + //! Set end of burst to true for the last packet in the chain. bool end_of_burst; /*! @@ -122,27 +122,27 @@ namespace uhd{ //! The channel number in a mimo configuration size_t channel; - /*! - * Time specification: when the async event occurred. - */ + //! Has time specification? bool has_time_spec; + + //! When the async event occurred. time_spec_t time_spec; /*! - * Event codes: - * - success: a packet was successfully transmitted - * - underflow: an internal send buffer has emptied - * - sequence error: packet loss between host and device - * - time error: packet had time that was late (or too early) - * - underflow in packet: underflow occurred inside a packet - * - sequence error in burst: packet loss within a burst + * The type of event for a receive async message call. */ enum event_code_t { + //! A packet was successfully transmitted. EVENT_CODE_SUCCESS = 0x1, + //! An internal send buffer has emptied. EVENT_CODE_UNDERFLOW = 0x2, + //! Packet loss between host and device. EVENT_CODE_SEQ_ERROR = 0x4, + //! Packet had time that was late (or too early). EVENT_CODE_TIME_ERROR = 0x8, + //! Underflow occurred inside a packet. EVENT_CODE_UNDERFLOW_IN_PACKET = 0x10, + //! Packet loss within a burst. EVENT_CODE_SEQ_ERROR_IN_BURST = 0x20 } event_code; }; diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp index f80d2cb15..b05ab5cc7 100644 --- a/host/include/uhd/types/tune_request.hpp +++ b/host/include/uhd/types/tune_request.hpp @@ -48,21 +48,19 @@ namespace uhd{ */ tune_request_t(double target_freq, double lo_off); - /*! - * Policy types for tune arguments: - * - None: do not set this argument, use current setting - * - Auto: automatically determine the argument's value - * - Manual: use the argument's value for the setting - */ + //! Policy options for tunable elements in the RF chain. enum policy_t { + //! Do not set this argument, use current setting. POLICY_NONE = 'N', + //! Automatically determine the argument's value. POLICY_AUTO = 'A', + //! Use the argument's value for the setting. POLICY_MANUAL = 'M' }; /*! * The target frequency of the overall chain in Hz. - * Use when one of the policies is set to automatic. + * Use in conjunction with the automatic policies. */ double target_freq; -- cgit v1.2.3 From cea3d05095202413be12cd4792ab9f781cbccef7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 26 Oct 2010 14:14:01 -0700 Subject: uhd: replaced print warning with a post warning call and registry renamed print warning calls in the implementation fixed issue with dict::pop so it now works even if the value is not comparable --- host/include/uhd/types/dict.hpp | 23 ++++++++---- host/include/uhd/types/tune_request.hpp | 2 +- host/include/uhd/usrp/mimo_usrp.hpp | 4 +-- host/include/uhd/usrp/simple_usrp.hpp | 2 +- host/include/uhd/utils/warning.hpp | 36 ++++++++++++++++--- host/lib/transport/udp_zero_copy_asio.cpp | 2 +- host/lib/usrp/dboard/db_basic_and_lf.cpp | 4 +-- host/lib/usrp/dboard/db_dbsrx.cpp | 8 ++--- host/lib/usrp/dboard/db_rfx.cpp | 4 +-- host/lib/usrp/dboard/db_tvrx.cpp | 2 +- host/lib/usrp/dboard/db_unknown.cpp | 4 +-- host/lib/usrp/dboard/db_wbx.cpp | 4 +-- host/lib/usrp/dboard_manager.cpp | 4 +-- host/lib/usrp/multi_usrp.cpp | 2 +- host/lib/usrp/usrp1/mboard_impl.cpp | 2 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 2 +- host/lib/usrp/wrapper_utils.hpp | 4 +-- host/lib/utils/thread_priority.cpp | 2 +- host/lib/utils/warning.cpp | 59 ++++++++++++++++++++++++++++--- host/test/warning_test.cpp | 4 +-- 20 files changed, 131 insertions(+), 43 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp index de96ea768..3d0acf888 100644 --- a/host/include/uhd/types/dict.hpp +++ b/host/include/uhd/types/dict.hpp @@ -120,10 +120,7 @@ namespace uhd{ BOOST_FOREACH(const pair_t &p, _map){ if (p.first == key) return p.second; } - throw std::invalid_argument(str(boost::format( - "key \"%s\" not found in dict(%s, %s)" - ) % boost::lexical_cast(key) - % typeid(Key).name() % typeid(Val).name())); + throw key_not_found_in_dict(key); } /*! @@ -147,12 +144,24 @@ namespace uhd{ * \throw an exception when not found */ Val pop(const Key &key){ - Val val = (*this)[key]; - _map.remove(pair_t(key, val)); - return val; + typename std::list::iterator it; + for (it = _map.begin(); it != _map.end(); it++){ + if (it->first != key) continue; + Val val = it->second; + _map.erase(it); + return val; + } + throw key_not_found_in_dict(key); } private: + std::exception key_not_found_in_dict(const Key &key) const{ + return std::out_of_range(str(boost::format( + "key \"%s\" not found in dict(%s, %s)" + ) % boost::lexical_cast(key) + % typeid(Key).name() % typeid(Val).name())); + } + std::list _map; //private container }; diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp index b05ab5cc7..942b93251 100644 --- a/host/include/uhd/types/tune_request.hpp +++ b/host/include/uhd/types/tune_request.hpp @@ -60,7 +60,7 @@ namespace uhd{ /*! * The target frequency of the overall chain in Hz. - * Use in conjunction with the automatic policies. + * Set this even if all policies are set to manual. */ double target_freq; diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index b5acf84e1..a2092f04f 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -298,7 +298,7 @@ public: time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as(); if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Detected time deviation between board %d and board 0.\n" "Board 0 time is %f seconds.\n" "Board %d time is %f seconds.\n" @@ -512,7 +512,7 @@ namespace uhd{ namespace usrp{ * The Make Function **********************************************************************/ inline mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( + uhd::warning::post( "The mimo USRP interface has been deprecated.\n" "Please switch to the multi USRP interface.\n" "#include \n" diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 59fd9bb09..77416dbbd 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -374,7 +374,7 @@ namespace uhd{ namespace usrp{ * The Make Function **********************************************************************/ inline simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( + uhd::warning::post( "The simple USRP interface has been deprecated.\n" "Please switch to the single USRP interface.\n" "#include \n" diff --git a/host/include/uhd/utils/warning.hpp b/host/include/uhd/utils/warning.hpp index 91d8400ab..a1e3f0d1e 100644 --- a/host/include/uhd/utils/warning.hpp +++ b/host/include/uhd/utils/warning.hpp @@ -19,16 +19,44 @@ #define INCLUDED_UHD_UTILS_WARNING_HPP #include +#include +#include #include -namespace uhd{ +namespace uhd{ namespace warning{ + + //! Callback function type for a message handler + typedef boost::function handler_t; /*! - * Print a formatted warning string to stderr. + * Post a warning message to all registered handlers. * \param msg the multiline warning message */ - UHD_API void print_warning(const std::string &msg); + UHD_API void post(const std::string &msg); + + /*! + * Register a new handler with this name. + * If the name was already registered for this name, + * the old registered handler will be replaced. + * \param name a unique name for this handler + * \param handler the callback handler function + */ + UHD_API void register_handler(const std::string &name, const handler_t &handler); + + /*! + * Unregister a handler for this name. + * \param name a unique name for a registered handler + * \return the handler that was registered + * \throw error when the name was not found in the registry + */ + UHD_API handler_t unregister_handler(const std::string &name); + + /*! + * Get a list of registered handler names. + * \return a vector of unique string names + */ + UHD_API const std::vector registry_names(void); -} //namespace uhd +}} //namespace uhd::warning #endif /* INCLUDED_UHD_UTILS_WARNING_HPP */ diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index d84aeefdd..ed29864e9 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -336,7 +336,7 @@ template static void resize_buff_helper( else std::cout << boost::format( "Current %s sock buff size: %d bytes" ) % name % actual_size << std::endl; - if (actual_size < target_size) uhd::print_warning(str(boost::format( + if (actual_size < target_size) uhd::warning::post(str(boost::format( "The %s buffer is smaller than the requested size.\n" "The minimum recommended buffer size is %d bytes.\n" "See the transport application notes on buffer resizing.\n%s" diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 5a87f4ecf..4c49b3bff 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -191,7 +191,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") % get_rx_id().to_pp_string() % _max_freq ) @@ -302,7 +302,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") % get_tx_id().to_pp_string() % _max_freq ) diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 10e7f292b..85251bdf9 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -175,7 +175,7 @@ UHD_STATIC_BLOCK(reg_dbsrx_dboard){ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){ //warn user about incorrect DBID on USRP1, requires R193 populated if (this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x000D) - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: incorrect dbid\n" "Expected dbid 0x0002 and R193\n" @@ -186,7 +186,7 @@ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){ //warn user about incorrect DBID on non-USRP1, requires R194 populated if (not this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x0002) - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: incorrect dbid\n" "Expected dbid 0x000D and R194\n" @@ -342,7 +342,7 @@ void dbsrx::set_lo_freq(double target_freq){ //vtune is too low, try lower frequency vco if (_max2118_read_regs.adc == 0){ if (_max2118_write_regs.osc_band == 0){ - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) @@ -356,7 +356,7 @@ void dbsrx::set_lo_freq(double target_freq){ //vtune is too high, try higher frequency vco if (_max2118_read_regs.adc == 7){ if (_max2118_write_regs.osc_band == 7){ - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 0eeb0bfdf..12e458d8c 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -487,7 +487,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; @@ -584,7 +584,7 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index c7aecf195..1f3c76556 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -484,7 +484,7 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("TVRX: No tunable bandwidth, fixed filtered to 6MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index 11293a1ba..a342471c4 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -164,7 +164,7 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) ); return; @@ -270,7 +270,7 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index b07f179a3..647f1b975 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -556,7 +556,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; @@ -657,7 +657,7 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index d73a698ae..5a98bb8eb 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -189,7 +189,7 @@ static args_t get_dboard_args( //verify that there is a registered constructor for this id if (not get_id_to_args_map().has_key(dboard_id)){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Unknown dboard ID: %s.\n" ) % dboard_id.to_pp_string())); return get_dboard_args(unit, dboard_id, true); @@ -217,7 +217,7 @@ dboard_manager_impl::dboard_manager_impl( //warn for invalid dboard id xcvr combinations if (rx_dboard_is_xcvr != this_dboard_is_xcvr or tx_dboard_is_xcvr != this_dboard_is_xcvr){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Unknown transceiver board ID combination...\n" "RX dboard ID: %s\n" "TX dboard ID: %s\n" diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 8b82502ba..024a6152d 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -145,7 +145,7 @@ public: time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as(); if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Detected time deviation between board %d and board 0.\n" "Board 0 time is %f seconds.\n" "Board %d time is %f seconds.\n" diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index fe3774eb4..669b20efa 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -98,7 +98,7 @@ static boost::uint32_t calc_rx_mux( // for all quadrature sources: Z = 0 // for mixed sources: warning + Z = 0 int Z = (num_quads > 0)? 0 : 1; - if (num_quads != 0 and num_reals != 0) uhd::print_warning( + if (num_quads != 0 and num_reals != 0) uhd::warning::post( "Mixing real and quadrature rx subdevices is not supported.\n" "The Q input to the real source(s) will be non-zero.\n" ); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 276ca86f6..314384e72 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -64,7 +64,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) ); } catch(...){ - uhd::print_warning( + uhd::warning::post( "Could not locate USRP1 firmware.\n" "Please install the images package.\n" ); diff --git a/host/lib/usrp/wrapper_utils.hpp b/host/lib/usrp/wrapper_utils.hpp index aee230fc0..6f9fdbfca 100644 --- a/host/lib/usrp/wrapper_utils.hpp +++ b/host/lib/usrp/wrapper_utils.hpp @@ -40,7 +40,7 @@ static inline void do_samp_rate_warning_message( ){ static const double max_allowed_error = 1.0; //Sps if (std::abs(target_rate - actual_rate) > max_allowed_error){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "The hardware does not support the requested %s sample rate:\n" "Target sample rate: %f MSps\n" "Actual sample rate: %f MSps\n" @@ -55,7 +55,7 @@ static inline void do_tune_freq_warning_message( ){ static const double max_allowed_error = 1.0; //Hz if (std::abs(target_freq - actual_freq) > max_allowed_error){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "The hardware does not support the requested %s frequency:\n" "Target frequency: %f MHz\n" "Actual frequency: %f MHz\n" diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp index f09d1b1d6..40b74f655 100644 --- a/host/lib/utils/thread_priority.cpp +++ b/host/lib/utils/thread_priority.cpp @@ -26,7 +26,7 @@ bool uhd::set_thread_priority_safe(float priority, bool realtime){ set_thread_priority(priority, realtime); return true; }catch(const std::exception &e){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "%s\n" "Failed to set thread priority %d (%s):\n" "Performance may be negatively affected.\n" diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp index 8a7d35a23..05be7ae4d 100644 --- a/host/lib/utils/warning.cpp +++ b/host/lib/utils/warning.cpp @@ -17,16 +17,67 @@ #include #include +#include +#include #include +#include +#include #include #include using namespace uhd; -void uhd::print_warning(const std::string &msg){ - //print the warning message - std::cerr << std::endl << "Warning:" << std::endl; +/*********************************************************************** + * Registry implementation + **********************************************************************/ +//create the registry for the handlers +typedef uhd::dict registry_t; +UHD_SINGLETON_FCN(registry_t, get_registry) + +//the default warning handler +static void stderr_warning(const std::string &msg){ + std::cerr << msg; +} + +//register a default handler +UHD_STATIC_BLOCK(warning_register_default){ + warning::register_handler("default", &stderr_warning); +} + +/*********************************************************************** + * Post + format + **********************************************************************/ +void warning::post(const std::string &msg){ + std::stringstream ss; + + //format the warning message + ss << std::endl << "Warning:" << std::endl; BOOST_FOREACH(const std::string &line, std::split_string(msg, "\n")){ - std::cerr << " " << line << std::endl; + ss << " " << line << std::endl; + } + + //post the formatted message + BOOST_FOREACH(const std::string &name, get_registry().keys()){ + get_registry()[name](ss.str()); } } + +/*********************************************************************** + * Registry accessor functions + **********************************************************************/ +void warning::register_handler( + const std::string &name, const handler_t &handler +){ + get_registry()[name] = handler; +} + +warning::handler_t warning::unregister_handler(const std::string &name){ + if (not get_registry().has_key(name)) throw std::runtime_error( + "The warning registry does not have a handler registered to " + name + ); + return get_registry().pop(name); +} + +const std::vector warning::registry_names(void){ + return get_registry().keys(); +} diff --git a/host/test/warning_test.cpp b/host/test/warning_test.cpp index 6202c4270..db19955de 100644 --- a/host/test/warning_test.cpp +++ b/host/test/warning_test.cpp @@ -19,9 +19,9 @@ #include #include -BOOST_AUTO_TEST_CASE(test_print_warning){ +BOOST_AUTO_TEST_CASE(test_warning_post){ std::cerr << "---begin print test ---" << std::endl; - uhd::print_warning( + uhd::warning::post( "This is a test print for a warning message.\n" "And this is the second line of the test print.\n" ); -- cgit v1.2.3 From a7840ebb3f7d7f807d05059e2809eb45cff04899 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 26 Oct 2010 18:11:40 -0700 Subject: uhd: moved templated dict implementation into ipp file --- host/include/uhd/types/CMakeLists.txt | 1 + host/include/uhd/types/dict.hpp | 87 ++++-------------------- host/include/uhd/types/dict.ipp | 120 ++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 75 deletions(-) create mode 100644 host/include/uhd/types/dict.ipp (limited to 'host/include') diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 661dd2d39..a96976b5e 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -19,6 +19,7 @@ INSTALL(FILES clock_config.hpp device_addr.hpp + dict.ipp dict.hpp io_type.hpp mac_addr.hpp diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp index 3d0acf888..b14fc5425 100644 --- a/host/include/uhd/types/dict.hpp +++ b/host/include/uhd/types/dict.hpp @@ -19,11 +19,6 @@ #define INCLUDED_UHD_TYPES_DICT_HPP #include -#include -#include -#include -#include -#include #include #include @@ -34,14 +29,10 @@ namespace uhd{ */ template class dict{ public: - typedef std::pair pair_t; - /*! * Create a new empty dictionary. */ - dict(void){ - /* NOP */ - } + dict(void); /*! * Input iterator constructor: @@ -50,64 +41,34 @@ namespace uhd{ * \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. - */ - ~dict(void){ - /* NOP */ - } + dict(InputIterator first, InputIterator last); /*! * Get the number of elements in this dict. * \return the number of elements */ - std::size_t size(void) const{ - return _map.size(); - } + std::size_t size(void) const; /*! * Get a list of the keys in this dict. * Key order depends on insertion precedence. * \return vector of keys */ - const std::vector keys(void) const{ - std::vector keys; - BOOST_FOREACH(const pair_t &p, _map){ - keys.push_back(p.first); - } - return keys; - } + const std::vector keys(void) const; /*! * Get a list of the values in this dict. * Value order depends on insertion precedence. * \return vector of values */ - const std::vector vals(void) const{ - std::vector vals; - BOOST_FOREACH(const pair_t &p, _map){ - vals.push_back(p.second); - } - return vals; - } + const std::vector vals(void) const; /*! * Does the dictionary contain this key? * \param key the key to look for * \return true if found */ - bool has_key(const Key &key) const{ - BOOST_FOREACH(const pair_t &p, _map){ - if (p.first == key) return true; - } - return false; - } + bool has_key(const Key &key) const; /*! * Get a value for the given key if it exists. @@ -116,12 +77,7 @@ namespace uhd{ * \return the value at the key * \throw an exception when not found */ - const Val &operator[](const Key &key) const{ - BOOST_FOREACH(const pair_t &p, _map){ - if (p.first == key) return p.second; - } - throw key_not_found_in_dict(key); - } + const Val &operator[](const Key &key) const; /*! * Set a value for the given key, however, in reality @@ -129,13 +85,7 @@ namespace uhd{ * \param key the key to set to * \return a reference to the value */ - Val &operator[](const Key &key){ - BOOST_FOREACH(pair_t &p, _map){ - if (p.first == key) return p.second; - } - _map.push_back(std::make_pair(key, Val())); - return _map.back().second; - } + Val &operator[](const Key &key); /*! * Pop an item out of the dictionary. @@ -143,28 +93,15 @@ namespace uhd{ * \return the value of the item * \throw an exception when not found */ - Val pop(const Key &key){ - typename std::list::iterator it; - for (it = _map.begin(); it != _map.end(); it++){ - if (it->first != key) continue; - Val val = it->second; - _map.erase(it); - return val; - } - throw key_not_found_in_dict(key); - } + Val pop(const Key &key); private: - std::exception key_not_found_in_dict(const Key &key) const{ - return std::out_of_range(str(boost::format( - "key \"%s\" not found in dict(%s, %s)" - ) % boost::lexical_cast(key) - % typeid(Key).name() % typeid(Val).name())); - } - + typedef std::pair pair_t; std::list _map; //private container }; } //namespace uhd +#include + #endif /* INCLUDED_UHD_TYPES_DICT_HPP */ diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp new file mode 100644 index 000000000..85071e6fd --- /dev/null +++ b/host/include/uhd/types/dict.ipp @@ -0,0 +1,120 @@ +// +// 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_DICT_IPP +#define INCLUDED_UHD_TYPES_DICT_IPP + +#include +#include +#include +#include +#include + +namespace uhd{ + + namespace /*anon*/{ + template + struct UHD_API key_not_found: std::out_of_range{ + key_not_found(const Key &key): std::out_of_range( + str(boost::format( + "key \"%s\" not found in dict(%s, %s)" + ) % boost::lexical_cast(key) + % typeid(Key).name() % typeid(Val).name() + ) + ){ + /* NOP */ + } + }; + } // namespace /*anon*/ + + template + dict::dict(void){ + /* NOP */ + } + + template + template + dict::dict(InputIterator first, InputIterator last){ + for(InputIterator it = first; it != last; it++){ + _map.push_back(*it); + } + } + + template + std::size_t dict::size(void) const{ + return _map.size(); + } + + template + const std::vector dict::keys(void) const{ + std::vector keys; + BOOST_FOREACH(const pair_t &p, _map){ + keys.push_back(p.first); + } + return keys; + } + + template + const std::vector dict::vals(void) const{ + std::vector vals; + BOOST_FOREACH(const pair_t &p, _map){ + vals.push_back(p.second); + } + return vals; + } + + template + bool dict::has_key(const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return true; + } + return false; + } + + template + const Val &dict::operator[](const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return p.second; + } + throw key_not_found(key); + } + + template + Val &dict::operator[](const Key &key){ + BOOST_FOREACH(pair_t &p, _map){ + if (p.first == key) return p.second; + } + _map.push_back(std::make_pair(key, Val())); + return _map.back().second; + } + + template + Val dict::pop(const Key &key){ + typename std::list::iterator it; + for (it = _map.begin(); it != _map.end(); it++){ + if (it->first == key){ + Val val = it->second; + _map.erase(it); + return val; + } + } + throw key_not_found(key); + } + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DICT_IPP */ -- cgit v1.2.3 From 211e190619652be145fdcd79cd54eda0e84d3313 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 10:45:15 -0700 Subject: usrp: added a time sync check for multi usrp --- host/include/uhd/usrp/multi_usrp.hpp | 8 ++++++++ host/lib/usrp/multi_usrp.cpp | 9 +++++++++ 2 files changed, 17 insertions(+) (limited to 'host/include') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 5380d177d..98ba07fc0 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -144,6 +144,14 @@ public: */ virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0; + /*! + * Are the times across all motherboards in this configuration synchronized? + * Checks that all time registers are approximately close but not exact, + * given that the RTT may varying for a control packet transaction. + * \return true when all motherboards time registers are in sync + */ + virtual bool get_time_synchronized(void) = 0; + /*! * Issue a stream command to the usrp device. * This tells the usrp to send samples into the host. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 024a6152d..876f1a3fc 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -154,6 +154,15 @@ public: } } + bool get_time_synchronized(void){ + for (size_t m = 1; m < get_num_mboards(); m++){ + time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as(); + if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)) return false; + } + return true; + } + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ for (size_t m = 0; m < get_num_mboards(); m++){ _mboard(m)[MBOARD_PROP_STREAM_CMD] = stream_cmd; -- cgit v1.2.3 From 630c007bbbabce90ffe3578d47ad7acc187bdc30 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 11:15:37 -0700 Subject: usrp: added to subdev spec comments/docs --- host/include/uhd/usrp/subdev_spec.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'host/include') diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp index 5de3bb3b8..b189724c9 100644 --- a/host/include/uhd/usrp/subdev_spec.hpp +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -26,10 +26,10 @@ namespace uhd{ namespace usrp{ /*! - * A subdevice specification (daughterboard, subdevice) name pairing. + * A subdevice specification (daughterboard slot, subdevice) name pairing. */ struct UHD_API subdev_spec_pair_t : boost::equality_comparable{ - //! The daughterboard name + //! The daughterboard slot name std::string db_name; //! The subdevice name @@ -50,7 +50,7 @@ namespace uhd{ namespace usrp{ UHD_API bool operator==(const subdev_spec_pair_t &, const subdev_spec_pair_t &); /*! - * A list of (daughterboard name, subdevice name) pairs: + * A list of (daughterboard slot name, subdevice name) pairs: * * A subdevice specification represents a list of subdevices on a motherboard. * The subdevices specified may span across multiple daughterboards; @@ -62,6 +62,11 @@ namespace uhd{ namespace usrp{ * The markup-string is a whitespace separated list of dboard:subdev pairs. * The first pair represents the subdevice for channel zero, * the second pair represents the subdevice for channel one, and so on. + * + * Special handling for empty conditions: + * - An empty subdevice specification means: select the first subdevice found in the configuration + * - An empty daughterboard name means: select the only daughterboard slot or error if multiple exist + * - An empty subdevice name means: select the only subdevice on that board or error if multiple exist */ class UHD_API subdev_spec_t : public std::vector{ public: -- cgit v1.2.3