From 1b3b856f5a5d06628d4176071cad424a146433c9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 17 Sep 2010 16:50:59 -0700 Subject: usrp2: provide clock over mimo connector so usrp2 can share refs --- host/lib/usrp/usrp2/clock_ctrl.cpp | 51 +++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 02227afad..1e1c9b7b8 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -20,6 +20,7 @@ #include "usrp2_regs.hpp" //spi slave constants #include #include +#include using namespace uhd; @@ -67,12 +68,60 @@ public: this->enable_dac_clock(true); this->enable_adc_clock(true); + /* always driving the mimo reference */ + this->enable_mimo_clock_out(true); } ~usrp2_clock_ctrl_impl(void){ - /* private clock enables, must be set here */ + //power down clock outputs + this->enable_external_ref(false); + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); this->enable_dac_clock(false); this->enable_adc_clock(false); + this->enable_mimo_clock_out(false); + } + + void enable_mimo_clock_out(bool enb){ + //FIXME TODO put this revision read in a common place + boost::uint8_t rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0); + + //calculate the low and high dividers + size_t divider = size_t(this->get_master_clock_rate()/10e6); + size_t high = divider/2; + size_t low = divider - high; + + switch(rev_hi){ + case 3: //clock 2 + _ad9510_regs.power_down_lvpecl_out2 = enb? + ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_NORMAL : + ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_SAFE_PD; + _ad9510_regs.output_level_lvpecl_out2 = ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT2_810MV; + //set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out2 = low - 1; + _ad9510_regs.divider_high_cycles_out2 = high - 1; + _ad9510_regs.bypass_divider_out2 = 0; + this->write_reg(0x3e); + this->write_reg(0x4c); + break; + + case 4: //clock 5 + _ad9510_regs.power_down_lvds_cmos_out5 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out5 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_LVDS; + _ad9510_regs.output_level_lvds_out5 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; + //set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out5 = low - 1; + _ad9510_regs.divider_high_cycles_out5 = high - 1; + _ad9510_regs.bypass_divider_out5 = 0; + this->write_reg(0x41); + this->write_reg(0x52); + break; + + //TODO FIXME do i want to throw, what about uninitialized boards? + //default: throw std::runtime_error("unknown rev hi in mboard eeprom"); + default: std::cerr << "unknown rev hi: " << rev_hi << std::endl; + } + this->update_regs(); } //uses output clock 7 (cmos) -- cgit v1.2.3 From 1625bcb4139a317189ff2a4c71b96473944aba50 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 20 Sep 2010 16:59:44 -0700 Subject: uhd: added single usrp interface, added usrp1 properties to prop names --- host/docs/coding.rst | 12 +- host/examples/benchmark_rx_rate.cpp | 8 +- host/examples/rx_timed_samples.cpp | 6 +- host/examples/test_async_messages.cpp | 12 +- host/examples/test_pps_input.cpp | 6 +- host/examples/tx_timed_samples.cpp | 6 +- host/examples/tx_waveforms.cpp | 6 +- host/include/uhd/device.hpp | 13 -- host/include/uhd/device.ipp | 26 --- host/include/uhd/usrp/CMakeLists.txt | 1 + host/include/uhd/usrp/simple_usrp.hpp | 2 +- host/include/uhd/usrp/single_usrp.hpp | 172 +++++++++++++++++++ host/lib/usrp/CMakeLists.txt | 1 + host/lib/usrp/single_usrp.cpp | 309 ++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp1/dsp_impl.cpp | 10 +- host/lib/usrp/usrp1/mboard_impl.cpp | 39 ++--- host/lib/usrp/usrp1/usrp1_impl.hpp | 6 + 17 files changed, 546 insertions(+), 89 deletions(-) create mode 100644 host/include/uhd/usrp/single_usrp.hpp create mode 100644 host/lib/usrp/single_usrp.cpp (limited to 'host/lib') diff --git a/host/docs/coding.rst b/host/docs/coding.rst index 23f350b0f..d6a19d250 100644 --- a/host/docs/coding.rst +++ b/host/docs/coding.rst @@ -23,11 +23,11 @@ The device API provides ways to: See the documentation in *device.hpp* for reference. ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -High-Level: The simple usrp +High-Level: The single usrp ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The goal of the simple usrp API is to wrap high level functions around the device properties. -The simple usrp provides a fat interface to access the most common properties. -The simple usrp provides ways to: +The goal of the single usrp API is to wrap high level functions around the device properties. +The single usrp provides a fat interface to access the most common properties. +The single usrp provides ways to: * Set and get daughterboard gains. * Set and get daughterboard antennas. @@ -38,13 +38,13 @@ The simple usrp provides ways to: * Set the usrp time registers. * Get the underlying device (as discussed above). -See the documentation in *usrp/simple_usrp.hpp* for reference. +See the documentation in *usrp/single_usrp.hpp* for reference. ^^^^^^^^^^^^^^^^^^^^^^^^^^^ High-Level: The mimo usrp ^^^^^^^^^^^^^^^^^^^^^^^^^^^ The mimo usrp API provides a wrapper around a device that represents several motherboards. -This API provides convenience calls just like the simple usrp, +This API provides convenience calls just like the single usrp, however the calls either work across all channels in the configuration, or take a channel argument to specify which channel to configure. The mimo usrp provides ways to: diff --git a/host/examples/benchmark_rx_rate.cpp b/host/examples/benchmark_rx_rate.cpp index 8fae813cf..36611f97f 100644 --- a/host/examples/benchmark_rx_rate.cpp +++ b/host/examples/benchmark_rx_rate.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -27,7 +27,7 @@ namespace po = boost::program_options; static inline void test_device( - uhd::usrp::simple_usrp::sptr sdev, + uhd::usrp::single_usrp::sptr sdev, double rx_rate_sps, double duration_secs ){ @@ -118,7 +118,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("duration", po::value(&duration)->default_value(10.0), "duration for each test in seconds") ("rate", po::value(&only_rate), "specify to perform a single test as this rate (sps)") ; @@ -135,7 +135,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; sdev->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); //stop if left running diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 4856f6779..441665900 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -38,7 +38,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to receive") ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") @@ -60,7 +60,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp index e02bc5f40..4c9d18121 100644 --- a/host/examples/test_async_messages.cpp +++ b/host/examples/test_async_messages.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ static const size_t async_to_ms = 100; * Send a burst of many samples that will fragment internally. * We expect to not get any async messages. */ -void test_no_async_message(uhd::usrp::simple_usrp::sptr sdev){ +void test_no_async_message(uhd::usrp::single_usrp::sptr sdev){ uhd::device::sptr dev = sdev->get_device(); std::cout << "Test no async message... " << std::flush; @@ -73,7 +73,7 @@ void test_no_async_message(uhd::usrp::simple_usrp::sptr sdev){ * Send a start of burst packet with no following end of burst. * We expect to get an underflow(within a burst) async message. */ -void test_underflow_message(uhd::usrp::simple_usrp::sptr sdev){ +void test_underflow_message(uhd::usrp::single_usrp::sptr sdev){ uhd::device::sptr dev = sdev->get_device(); std::cout << "Test underflow message... " << std::flush; @@ -117,7 +117,7 @@ void test_underflow_message(uhd::usrp::simple_usrp::sptr sdev){ * Send a burst packet that occurs at a time in the past. * We expect to get a time error async message. */ -void test_time_error_message(uhd::usrp::simple_usrp::sptr sdev){ +void test_time_error_message(uhd::usrp::single_usrp::sptr sdev){ uhd::device::sptr dev = sdev->get_device(); std::cout << "Test time error message... " << std::flush; @@ -170,7 +170,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("rate", po::value(&rate)->default_value(1.5e6), "rate of outgoing samples") ; po::variables_map vm; @@ -186,7 +186,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; //set the tx sample rate diff --git a/host/examples/test_pps_input.cpp b/host/examples/test_pps_input.cpp index e01d32910..d1b49d320 100644 --- a/host/examples/test_pps_input.cpp +++ b/host/examples/test_pps_input.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -37,7 +37,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -52,7 +52,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 5b72bd72f..f34c121d5 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -40,7 +40,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit") ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to transmit") ("spp", po::value(&samps_per_packet)->default_value(1000), "number of samples per packet") @@ -64,7 +64,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 3f319cf68..50982cf88 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include //system time #include @@ -70,7 +70,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("duration", po::value(&total_duration)->default_value(3), "number of seconds to transmit") ("spb", po::value(&spb)->default_value(10000), "samples per buffer") ("rate", po::value(&rate)->default_value(1.5e6), "rate of outgoing samples") @@ -93,7 +93,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index c48b3dfff..2077cae62 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -26,7 +26,6 @@ #include #include #include -#include #include namespace uhd{ @@ -140,12 +139,6 @@ public: send_mode_t send_mode ); - //! Deprecated - size_t send( - const boost::asio::const_buffer &, const tx_metadata_t &, - const io_type_t &, send_mode_t send_mode - ); - /*! * Receive buffers containing IF data described by the metadata. * @@ -196,12 +189,6 @@ public: size_t timeout_ms = default_recv_timeout_ms ); - //! Deprecated - size_t recv( - const boost::asio::mutable_buffer &, rx_metadata_t &, - const io_type_t &, recv_mode_t - ); - /*! * Get the maximum number of samples per packet on send. * \return the number of samples diff --git a/host/include/uhd/device.ipp b/host/include/uhd/device.ipp index 603c52859..60a3f535d 100644 --- a/host/include/uhd/device.ipp +++ b/host/include/uhd/device.ipp @@ -34,19 +34,6 @@ namespace uhd{ ); } - UHD_DEPRECATED UHD_INLINE size_t device::send( - const boost::asio::const_buffer &buff, - const tx_metadata_t &metadata, - const io_type_t &io_type, - send_mode_t send_mode - ){ - return this->send( - boost::asio::buffer_cast(buff), - boost::asio::buffer_size(buff)/io_type.size, - metadata, io_type, send_mode - ); - } - UHD_INLINE size_t device::recv( void *buff, size_t nsamps_per_buff, @@ -62,19 +49,6 @@ namespace uhd{ ); } - UHD_DEPRECATED UHD_INLINE size_t device::recv( - const boost::asio::mutable_buffer &buff, - rx_metadata_t &metadata, - const io_type_t &io_type, - recv_mode_t recv_mode - ){ - return this->recv( - boost::asio::buffer_cast(buff), - boost::asio::buffer_size(buff)/io_type.size, - metadata, io_type, recv_mode - ); - } - } //namespace uhd #endif /* INCLUDED_UHD_DEVICE_IPP */ diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index 130956f8a..f973e401a 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -40,6 +40,7 @@ INSTALL(FILES ### interfaces ### simple_usrp.hpp + single_usrp.hpp mimo_usrp.hpp DESTINATION ${INCLUDE_DIR}/uhd/usrp diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 08b9c01ea..169411f19 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -38,7 +38,7 @@ namespace uhd{ namespace usrp{ * The wrapper provides convenience functions to tune the devices * as well as to set the dboard gains, antennas, and other properties. */ -class UHD_API simple_usrp : boost::noncopyable{ +class UHD_API UHD_DEPRECATED simple_usrp : boost::noncopyable{ public: typedef boost::shared_ptr sptr; diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp new file mode 100644 index 000000000..1b89a3620 --- /dev/null +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -0,0 +1,172 @@ +// +// 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_SINGLE_USRP_HPP +#define INCLUDED_UHD_USRP_SINGLE_USRP_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ namespace usrp{ + +/*! + * 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. + */ +class UHD_API single_usrp : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a new single 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; + + /*! + * Get a printable name for this usrp. + * \return a printable string + */ + virtual std::string get_pp_string(void) = 0; + + /******************************************************************* + * Misc + ******************************************************************/ + /*! + * 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; + + /*! + * Sets the time registers on the usrp immediately. + * \param time_spec the time to latch into the usrp device + */ + virtual void set_time_now(const time_spec_t &time_spec) = 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; + + /*! + * 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 + */ + virtual void set_clock_config(const clock_config_t &clock_config) = 0; + + /******************************************************************* + * RX methods + ******************************************************************/ + 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 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) = 0; + virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan = 0) = 0; + virtual double get_rx_freq(size_t chan = 0) = 0; + virtual freq_range_t get_rx_freq_range(size_t chan = 0) = 0; + + virtual void set_rx_gain(float gain, size_t chan = 0) = 0; + virtual float get_rx_gain(size_t chan = 0) = 0; + virtual gain_range_t get_rx_gain_range(size_t chan = 0) = 0; + + virtual void set_rx_antenna(const std::string &ant, size_t chan = 0) = 0; + virtual std::string get_rx_antenna(size_t chan = 0) = 0; + virtual std::vector get_rx_antennas(size_t chan = 0) = 0; + + virtual bool get_rx_lo_locked(size_t chan = 0) = 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) = 0; + + virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; + + /******************************************************************* + * TX methods + ******************************************************************/ + 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 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) = 0; + virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan = 0) = 0; + virtual double get_tx_freq(size_t chan = 0) = 0; + virtual freq_range_t get_tx_freq_range(size_t chan = 0) = 0; + + virtual void set_tx_gain(float gain, size_t chan = 0) = 0; + virtual float get_tx_gain(size_t chan = 0) = 0; + virtual gain_range_t get_tx_gain_range(size_t chan = 0) = 0; + + virtual void set_tx_antenna(const std::string &ant, size_t chan = 0) = 0; + virtual std::string get_tx_antenna(size_t chan = 0) = 0; + virtual std::vector get_tx_antennas(size_t chan = 0) = 0; + + virtual bool get_tx_lo_locked(size_t chan = 0) = 0; + + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; +}; + +}} + +#endif /* INCLUDED_UHD_USRP_SINGLE_USRP_HPP */ diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index b5c545988..69a190bfa 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -26,6 +26,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.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/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp new file mode 100644 index 000000000..77e705c71 --- /dev/null +++ b/host/lib/usrp/single_usrp.cpp @@ -0,0 +1,309 @@ +// +// 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 + +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 single_usrp_impl : public single_usrp{ +public: + single_usrp_impl(const device_addr_t &addr){ + _dev = device::make(addr); + } + + ~single_usrp_impl(void){ + /* NOP */ + } + + device::sptr get_device(void){ + return _dev; + } + + std::string get_pp_string(void){ + std::string buff = str(boost::format( + "Single USRP:\n" + " Device: %s\n" + " Mboard: %s\n" + ) + % (*_dev)[DEVICE_PROP_NAME].as() + % _mboard()[MBOARD_PROP_NAME].as() + ); + + //----------- rx side of life ---------------------------------- + buff += str(boost::format( + " RX DSP: %s\n" + ) + % _rx_dsp()[DSP_PROP_NAME].as() + ); + for (size_t chan = 0; chan < this->get_rx_subdev_spec().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 ---------------------------------- + buff += str(boost::format( + " TX DSP: %s\n" + ) + % _tx_dsp()[DSP_PROP_NAME].as() + ); + for (size_t chan = 0; chan < this->get_tx_subdev_spec().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; + } + + /******************************************************************* + * Misc + ******************************************************************/ + time_spec_t get_time_now(void){ + return _mboard()[MBOARD_PROP_TIME_NOW].as(); + } + + void set_time_now(const time_spec_t &time_spec){ + _mboard()[MBOARD_PROP_TIME_NOW] = time_spec; + } + + void set_time_next_pps(const time_spec_t &time_spec){ + _mboard()[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + } + + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + _mboard()[MBOARD_PROP_STREAM_CMD] = stream_cmd; + } + + void set_clock_config(const clock_config_t &clock_config){ + _mboard()[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_subdev_spec(const subdev_spec_t &spec){ + _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; + std::cout << "RX " << this->get_rx_subdev_spec().to_pp_string() << std::endl; + } + + subdev_spec_t get_rx_subdev_spec(void){ + return _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as(); + } + + void set_rx_rate(double rate){ + _rx_dsp()[DSP_PROP_HOST_RATE] = rate; + } + + double get_rx_rate(void){ + return _rx_dsp()[DSP_PROP_HOST_RATE].as(); + } + + tune_result_t set_rx_freq(double target_freq, size_t chan){ + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(/*TODO*/), target_freq); + } + + tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(/*TODO*/), target_freq, lo_off); + } + + double get_rx_freq(size_t chan){ + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(/*TODO*/)); + } + + freq_range_t get_rx_freq_range(size_t chan){ + 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); + } + + 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(); + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_subdev_spec(const subdev_spec_t &spec){ + _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; + std::cout << "TX " << this->get_tx_subdev_spec().to_pp_string() << std::endl; + } + + subdev_spec_t get_tx_subdev_spec(void){ + return _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as(); + } + + void set_tx_rate(double rate){ + _tx_dsp()[DSP_PROP_HOST_RATE] = rate; + } + + double get_tx_rate(void){ + return _tx_dsp()[DSP_PROP_HOST_RATE].as(); + } + + tune_result_t set_tx_freq(double target_freq, size_t chan){ + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(/*TODO*/), target_freq); + } + + tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(/*TODO*/), target_freq, lo_off); + } + + double get_tx_freq(size_t chan){ + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(/*TODO*/)); + } + + freq_range_t get_tx_freq_range(size_t chan){ + 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); + } + + 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(void){ + return (*_dev)[DEVICE_PROP_MBOARD]; + } + wax::obj _rx_dsp(void){ + return _mboard()[MBOARD_PROP_RX_DSP]; + } + wax::obj _tx_dsp(void){ + return _mboard()[MBOARD_PROP_TX_DSP]; + } + wax::obj _rx_dboard(size_t chan){ + std::string db_name = this->get_rx_subdev_spec().at(chan).db_name; + return _mboard()[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + } + wax::obj _tx_dboard(size_t chan){ + std::string db_name = this->get_tx_subdev_spec().at(chan).db_name; + return _mboard()[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + } + wax::obj _rx_subdev(size_t chan){ + std::string sd_name = this->get_rx_subdev_spec().at(chan).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 = this->get_tx_subdev_spec().at(chan).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 = this->get_rx_subdev_spec().at(chan).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 = this->get_tx_subdev_spec().at(chan).sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } +}; + +/*********************************************************************** + * The Make Function + **********************************************************************/ +single_usrp::sptr single_usrp::make(const device_addr_t &dev_addr){ + return sptr(new single_usrp_impl(dev_addr)); +} diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index d5a88fa2d..ba05fa6ed 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -46,7 +46,10 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val) { switch(key.as()){ case DSP_PROP_NAME: - val = std::string("usrp1 ddc0"); + val = str(boost::format("usrp1 ddc %uX %s") + % this->get_num_ddcs() + % (this->has_rx_halfband()? "+ hb" : "") + ); return; case DSP_PROP_OTHERS: @@ -137,7 +140,10 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val) { switch(key.as()) { case DSP_PROP_NAME: - val = std::string("usrp1 duc0"); + val = str(boost::format("usrp1 duc %uX %s") + % this->get_num_ducs() + % (this->has_tx_halfband()? "+ hb" : "") + ); return; case DSP_PROP_OTHERS: diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index a90532cb8..464a82494 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -172,23 +172,23 @@ static boost::uint32_t calc_tx_mux( * | Reserved |T|DUCs |R|DDCs | * +-----------------------------------------------+-+-----+-+-----+ */ -static int num_ddcs(boost::uint32_t regval) -{ +size_t usrp1_impl::get_num_ddcs(void){ + boost::uint32_t regval = _iface->peek32(FR_RB_CAPS); return (regval >> 0) & 0x0007; } -static int num_ducs(boost::uint32_t regval) -{ +size_t usrp1_impl::get_num_ducs(void){ + boost::uint32_t regval = _iface->peek32(FR_RB_CAPS); return (regval >> 4) & 0x0007; } -static bool has_rx_halfband(boost::uint32_t regval) -{ +bool usrp1_impl::has_rx_halfband(void){ + boost::uint32_t regval = _iface->peek32(FR_RB_CAPS); return (regval >> 3) & 0x0001; } -static bool has_tx_halfband(boost::uint32_t regval) -{ +bool usrp1_impl::has_tx_halfband(void){ + boost::uint32_t regval = _iface->peek32(FR_RB_CAPS); return (regval >> 7) & 0x0001; } @@ -224,22 +224,23 @@ void usrp1_impl::mboard_init(void) // // Do something useful with the capabilities register // - boost::uint32_t regval = _iface->peek32(FR_RB_CAPS); std::cout << "USRP1 Capabilities" << std::endl; - std::cout << " number of duc's: " << num_ddcs(regval) << std::endl; - std::cout << " number of ddc's: " << num_ducs(regval) << std::endl; - std::cout << " rx halfband: " << has_rx_halfband(regval) << std::endl; - std::cout << " tx halfband: " << has_tx_halfband(regval) << std::endl; + std::cout << " number of duc's: " << get_num_ddcs() << std::endl; + std::cout << " number of ddc's: " << get_num_ducs() << std::endl; + std::cout << " rx halfband: " << has_rx_halfband() << std::endl; + std::cout << " tx halfband: " << has_tx_halfband() << std::endl; } void usrp1_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd) { - if (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS) { - _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, true, 0, 0, 0); - } + switch(stream_cmd.stream_mode){ + case stream_cmd_t::STREAM_MODE_START_CONTINUOUS: + return _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, true, 0, 0, 0); + + case stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS: + return _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, false, 0, 0, 0); - if (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS) { - _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, false, 0, 0, 0); + default: throw std::runtime_error("unsupported stream command type for USRP1"); } } @@ -269,7 +270,7 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) //handle the get request conditioned on the key switch(key.as()){ case MBOARD_PROP_NAME: - val = std::string("usrp1 mboard"); + val = std::string("usrp1 mboard - " + (*_mboard_proxy)[std::string("serial")].as()); return; case MBOARD_PROP_OTHERS: diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index c2f693eeb..663fbb34b 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -192,6 +192,12 @@ private: //transports uhd::transport::usb_zero_copy::sptr _data_transport; usrp_ctrl::sptr _ctrl_transport; + + //capabilities + size_t get_num_ducs(void); + size_t get_num_ddcs(void); + bool has_rx_halfband(void); + bool has_tx_halfband(void); }; #endif /* INCLUDED_USRP1_IMPL_HPP */ -- cgit v1.2.3 From d68922ed306cd73eb761165369619cdbac2ca637 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 20 Sep 2010 18:17:52 -0700 Subject: usrp1: implemented multi-channel dsp control of shift freq usrp: simple usrp calls into single usrp and prints deprecation warning usrp: tune helper now supports multi-channel dsps --- host/include/uhd/usrp/dsp_props.hpp | 11 +-- host/include/uhd/usrp/simple_usrp.hpp | 3 +- host/include/uhd/usrp/tune_helper.hpp | 18 ++-- host/lib/usrp/mimo_usrp.cpp | 12 +-- host/lib/usrp/simple_usrp.cpp | 163 +++++++++++----------------------- host/lib/usrp/single_usrp.cpp | 14 ++- host/lib/usrp/tune_helper.cpp | 38 ++++---- host/lib/usrp/usrp1/dsp_impl.cpp | 77 ++++++++++------ host/lib/usrp/usrp1/mboard_impl.cpp | 34 ++++--- host/lib/usrp/usrp1/usrp1_impl.hpp | 6 +- host/test/tune_helper_test.cpp | 22 +++-- 11 files changed, 191 insertions(+), 207 deletions(-) (limited to 'host/lib') diff --git a/host/include/uhd/usrp/dsp_props.hpp b/host/include/uhd/usrp/dsp_props.hpp index 75d8c0a60..54ea5666b 100644 --- a/host/include/uhd/usrp/dsp_props.hpp +++ b/host/include/uhd/usrp/dsp_props.hpp @@ -37,11 +37,12 @@ namespace uhd{ namespace usrp{ * Set the shift property and read it back to get actual shift. */ enum dsp_prop_t{ - DSP_PROP_NAME = 'n', //ro, std::string - DSP_PROP_OTHERS = 'o', //ro, prop_names_t - DSP_PROP_FREQ_SHIFT = 'f', //rw, double Hz - DSP_PROP_CODEC_RATE = 'c', //ro, double Sps - DSP_PROP_HOST_RATE = 'h' //rw, double Sps + DSP_PROP_NAME = 'n', //ro, std::string + DSP_PROP_OTHERS = 'o', //ro, prop_names_t + DSP_PROP_FREQ_SHIFT = 'f', //rw, double Hz + DSP_PROP_FREQ_SHIFT_NAMES = 'F', //ro, prop_names_t + DSP_PROP_CODEC_RATE = 'c', //ro, double Sps + DSP_PROP_HOST_RATE = 'h' //rw, double Sps }; }} //namespace diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 169411f19..6149f739c 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -33,7 +33,8 @@ namespace uhd{ namespace usrp{ /*! - * The simple USRP device class: + * The simple USRP device class (DEPRECATED): + * This interface has been deprecated in favor of the single USRP interface. * A simple 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. diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp index df3907b3e..ec133fa08 100644 --- a/host/include/uhd/usrp/tune_helper.hpp +++ b/host/include/uhd/usrp/tune_helper.hpp @@ -31,12 +31,13 @@ namespace uhd{ namespace usrp{ * The ddc cordic is setup to bring the IF down to baseband. * \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 * \return a tune result struct */ UHD_API tune_result_t tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, + wax::obj subdev, wax::obj ddc, size_t chan, double target_freq, double lo_offset ); @@ -46,17 +47,19 @@ namespace uhd{ namespace usrp{ * is calculated based on the subdevice and BW. */ UHD_API tune_result_t tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, double target_freq + wax::obj subdev, wax::obj ddc, + size_t chan, double target_freq ); /*! * Calculate the overall frequency from the combination of dboard IF and DDC shift. * \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 * \return the overall tune frequency of the system in Hz */ UHD_API double derive_freq_from_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc + wax::obj subdev, wax::obj ddc, size_t chan ); /*! @@ -66,12 +69,13 @@ namespace uhd{ namespace usrp{ * The duc cordic is setup to bring the baseband up to IF. * \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 * \return a tune result struct */ UHD_API tune_result_t tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, + wax::obj subdev, wax::obj duc, size_t chan, double target_freq, double lo_offset ); @@ -81,17 +85,19 @@ namespace uhd{ namespace usrp{ * is calculated based on the subdevice and BW. */ UHD_API tune_result_t tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, double target_freq + wax::obj subdev, wax::obj duc, + size_t chan, double target_freq ); /*! * Calculate the overall frequency from the combination of dboard IF and DUC shift. * \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 * \return the overall tune frequency of the system in Hz */ UHD_API double derive_freq_from_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc + wax::obj subdev, wax::obj duc, size_t chan ); }} diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index e78d38fc0..9331c7fbb 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -179,15 +179,15 @@ public: } tune_result_t set_rx_freq(size_t chan, double target_freq){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 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), target_freq, 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)); + 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){ @@ -255,15 +255,15 @@ public: } tune_result_t set_tx_freq(size_t chan, double target_freq){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 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), target_freq, 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)); + 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){ diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index e573d0fc0..d29952955 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -15,35 +15,20 @@ // 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 simple_usrp_impl : public simple_usrp{ public: simple_usrp_impl(const device_addr_t &addr){ - _dev = device::make(addr); + _sdev = single_usrp::make(addr); } ~simple_usrp_impl(void){ @@ -51,235 +36,187 @@ public: } device::sptr get_device(void){ - return _dev; + return _sdev->get_device(); } std::string get_pp_string(void){ - return str(boost::format( - "Simple USRP:\n" - " Device: %s\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" - ) - % (*_dev)[DEVICE_PROP_NAME].as() - % _mboard()[MBOARD_PROP_NAME].as() - % _rx_dsp()[DSP_PROP_NAME].as() - % _rx_dboard()[DBOARD_PROP_NAME].as() - % _rx_subdev()[SUBDEV_PROP_NAME].as() - % _tx_dsp()[DSP_PROP_NAME].as() - % _tx_dboard()[DBOARD_PROP_NAME].as() - % _tx_subdev()[SUBDEV_PROP_NAME].as() - ); + return _sdev->get_pp_string(); } /******************************************************************* * Misc ******************************************************************/ time_spec_t get_time_now(void){ - return _mboard()[MBOARD_PROP_TIME_NOW].as(); + return _sdev->get_time_now(); } void set_time_now(const time_spec_t &time_spec){ - _mboard()[MBOARD_PROP_TIME_NOW] = time_spec; + return _sdev->set_time_now(time_spec); } void set_time_next_pps(const time_spec_t &time_spec){ - _mboard()[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + return _sdev->set_time_next_pps(time_spec); } void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - _mboard()[MBOARD_PROP_STREAM_CMD] = stream_cmd; + return _sdev->issue_stream_cmd(stream_cmd); } void set_clock_config(const clock_config_t &clock_config){ - _mboard()[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + return _sdev->set_clock_config(clock_config); } /******************************************************************* * RX methods ******************************************************************/ void set_rx_subdev_spec(const subdev_spec_t &spec){ - _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; - std::cout << "RX " << _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as().to_pp_string() << std::endl; + return _sdev->set_rx_subdev_spec(spec); } subdev_spec_t get_rx_subdev_spec(void){ - return _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as(); + return _sdev->get_rx_subdev_spec(); } void set_rx_rate(double rate){ - _rx_dsp()[DSP_PROP_HOST_RATE] = rate; + return _sdev->set_rx_rate(rate); } double get_rx_rate(void){ - return _rx_dsp()[DSP_PROP_HOST_RATE].as(); + return _sdev->get_rx_rate(); } tune_result_t set_rx_freq(double target_freq){ - return tune_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp(), target_freq); + return _sdev->set_rx_freq(target_freq); } tune_result_t set_rx_freq(double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp(), target_freq, lo_off); + return _sdev->set_rx_freq(target_freq, lo_off); } double get_rx_freq(void){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp()); + return _sdev->get_rx_freq(); } freq_range_t get_rx_freq_range(void){ - return add_dsp_shift(_rx_subdev()[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp()); + return _sdev->get_rx_freq_range(); } void set_rx_gain(float gain){ - return _rx_gain_group()->set_value(gain); + return _sdev->set_rx_gain(gain); } float get_rx_gain(void){ - return _rx_gain_group()->get_value(); + return _sdev->get_rx_gain(); } gain_range_t get_rx_gain_range(void){ - return _rx_gain_group()->get_range(); + return _sdev->get_rx_gain_range(); } void set_rx_antenna(const std::string &ant){ - _rx_subdev()[SUBDEV_PROP_ANTENNA] = ant; + return _sdev->set_rx_antenna(ant); } std::string get_rx_antenna(void){ - return _rx_subdev()[SUBDEV_PROP_ANTENNA].as(); + return _sdev->get_rx_antenna(); } std::vector get_rx_antennas(void){ - return _rx_subdev()[SUBDEV_PROP_ANTENNA_NAMES].as(); + return _sdev->get_rx_antennas(); } bool get_rx_lo_locked(void){ - return _rx_subdev()[SUBDEV_PROP_LO_LOCKED].as(); + return _sdev->get_rx_lo_locked(); } float read_rssi(void){ - return _rx_subdev()[SUBDEV_PROP_RSSI].as(); + return _sdev->read_rssi(); } dboard_iface::sptr get_rx_dboard_iface(void){ - return _rx_dboard()[DBOARD_PROP_DBOARD_IFACE].as(); + return _sdev->get_rx_dboard_iface(); } /******************************************************************* * TX methods ******************************************************************/ void set_tx_subdev_spec(const subdev_spec_t &spec){ - _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; - std::cout << "TX " << _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as().to_pp_string() << std::endl; + return _sdev->set_tx_subdev_spec(spec); } subdev_spec_t get_tx_subdev_spec(void){ - return _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as(); + return _sdev->get_tx_subdev_spec(); } void set_tx_rate(double rate){ - _tx_dsp()[DSP_PROP_HOST_RATE] = rate; + return _sdev->set_tx_rate(rate); } double get_tx_rate(void){ - return _tx_dsp()[DSP_PROP_HOST_RATE].as(); + return _sdev->get_tx_rate(); } tune_result_t set_tx_freq(double target_freq){ - return tune_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp(), target_freq); + return _sdev->set_tx_freq(target_freq); } tune_result_t set_tx_freq(double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp(), target_freq, lo_off); + return _sdev->set_tx_freq(target_freq, lo_off); } double get_tx_freq(void){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp()); + return _sdev->get_tx_freq(); } freq_range_t get_tx_freq_range(void){ - return add_dsp_shift(_tx_subdev()[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp()); + return _sdev->get_tx_freq_range(); } void set_tx_gain(float gain){ - return _tx_gain_group()->set_value(gain); + return _sdev->set_tx_gain(gain); } float get_tx_gain(void){ - return _tx_gain_group()->get_value(); + return _sdev->get_tx_gain(); } gain_range_t get_tx_gain_range(void){ - return _tx_gain_group()->get_range(); + return _sdev->get_tx_gain_range(); } void set_tx_antenna(const std::string &ant){ - _tx_subdev()[SUBDEV_PROP_ANTENNA] = ant; + return _sdev->set_tx_antenna(ant); } std::string get_tx_antenna(void){ - return _tx_subdev()[SUBDEV_PROP_ANTENNA].as(); + return _sdev->get_tx_antenna(); } std::vector get_tx_antennas(void){ - return _tx_subdev()[SUBDEV_PROP_ANTENNA_NAMES].as(); + return _sdev->get_tx_antennas(); } bool get_tx_lo_locked(void){ - return _tx_subdev()[SUBDEV_PROP_LO_LOCKED].as(); + return _sdev->get_tx_lo_locked(); } dboard_iface::sptr get_tx_dboard_iface(void){ - return _tx_dboard()[DBOARD_PROP_DBOARD_IFACE].as(); + return _sdev->get_tx_dboard_iface(); } private: - device::sptr _dev; - wax::obj _mboard(void){ - return (*_dev)[DEVICE_PROP_MBOARD]; - } - wax::obj _rx_dsp(void){ - return _mboard()[MBOARD_PROP_RX_DSP]; - } - wax::obj _tx_dsp(void){ - return _mboard()[MBOARD_PROP_TX_DSP]; - } - wax::obj _rx_dboard(void){ - std::string db_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().db_name; - return _mboard()[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; - } - wax::obj _tx_dboard(void){ - std::string db_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().db_name; - return _mboard()[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; - } - wax::obj _rx_subdev(void){ - std::string sd_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; - return _rx_dboard()[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; - } - wax::obj _tx_subdev(void){ - std::string sd_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; - return _tx_dboard()[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; - } - gain_group::sptr _rx_gain_group(void){ - std::string sd_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; - return _rx_dboard()[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); - } - gain_group::sptr _tx_gain_group(void){ - std::string sd_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; - return _tx_dboard()[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); - } + 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" + "simple_usrp::sptr sdev = simple_usrp::make(args);\n" + ); return sptr(new simple_usrp_impl(dev_addr)); } diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 77e705c71..bb4af44b8 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -129,7 +129,6 @@ public: ******************************************************************/ void set_rx_subdev_spec(const subdev_spec_t &spec){ _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; - std::cout << "RX " << this->get_rx_subdev_spec().to_pp_string() << std::endl; } subdev_spec_t get_rx_subdev_spec(void){ @@ -145,15 +144,15 @@ public: } tune_result_t set_rx_freq(double target_freq, size_t chan){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(/*TODO*/), target_freq); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq); } tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(/*TODO*/), target_freq, lo_off); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq, lo_off); } double get_rx_freq(size_t chan){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(/*TODO*/)); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan); } freq_range_t get_rx_freq_range(size_t chan){ @@ -201,7 +200,6 @@ public: ******************************************************************/ void set_tx_subdev_spec(const subdev_spec_t &spec){ _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; - std::cout << "TX " << this->get_tx_subdev_spec().to_pp_string() << std::endl; } subdev_spec_t get_tx_subdev_spec(void){ @@ -217,15 +215,15 @@ public: } tune_result_t set_tx_freq(double target_freq, size_t chan){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(/*TODO*/), target_freq); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq); } tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(/*TODO*/), target_freq, lo_off); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq, lo_off); } double get_tx_freq(size_t chan){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(/*TODO*/)); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan); } freq_range_t get_tx_freq_range(size_t chan){ diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index e516477d3..7633c67f2 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -30,11 +30,12 @@ using namespace uhd::usrp; **********************************************************************/ static tune_result_t tune_xx_subdev_and_dxc( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dxc, + wax::obj subdev, wax::obj dxc, size_t chan, double target_freq, double lo_offset ){ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; - wax::obj dxc_freq_proxy = dxc[DSP_PROP_FREQ_SHIFT]; + 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(); // Ask the d'board to tune as closely as it can to target_freq+lo_offset @@ -65,11 +66,12 @@ static tune_result_t tune_xx_subdev_and_dxc( static double derive_freq_from_xx_subdev_and_dxc( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dxc + wax::obj subdev, wax::obj dxc, size_t chan ){ //extract actual dsp and IF frequencies double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as(); - double actual_dxc_freq = dxc[DSP_PROP_FREQ_SHIFT].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(); //invert the sign on the dxc freq given the following conditions if (unit == dboard_iface::UNIT_TX) actual_dxc_freq *= -1.0; @@ -81,50 +83,54 @@ static double derive_freq_from_xx_subdev_and_dxc( * RX Tune **********************************************************************/ tune_result_t usrp::tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, + 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, target_freq, 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, - double target_freq + 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*ddc[DSP_PROP_HOST_RATE].as(); } - return tune_rx_subdev_and_dsp(subdev, ddc, target_freq, lo_offset); + return tune_rx_subdev_and_dsp(subdev, ddc, chan, target_freq, lo_offset); } -double usrp::derive_freq_from_rx_subdev_and_dsp(wax::obj subdev, wax::obj ddc){ - return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc); +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); } /*********************************************************************** * TX Tune **********************************************************************/ tune_result_t usrp::tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, + wax::obj subdev, wax::obj duc, size_t chan, double target_freq, double lo_offset ){ - return tune_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, target_freq, lo_offset); + 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, - double target_freq + 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, target_freq, lo_offset); + return tune_tx_subdev_and_dsp(subdev, duc, chan, target_freq, lo_offset); } -double usrp::derive_freq_from_tx_subdev_and_dsp(wax::obj subdev, wax::obj duc){ - return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc); +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); } diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index ba05fa6ed..573bce21f 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -42,8 +44,9 @@ void usrp1_impl::rx_dsp_init(void) /*********************************************************************** * RX DDC Get **********************************************************************/ -void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val) -{ +void usrp1_impl::rx_dsp_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_NAME: val = str(boost::format("usrp1 ddc %uX %s") @@ -57,7 +60,16 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_FREQ_SHIFT: - val = _rx_dsp_freq; + val = _rx_dsp_freqs[key.name]; + return; + + case DSP_PROP_FREQ_SHIFT_NAMES:{ + prop_names_t names; + for(size_t i = 0; i < this->get_num_ddcs(); i++){ + names.push_back(boost::lexical_cast(i)); + } + val = names; + } return; case DSP_PROP_CODEC_RATE: @@ -76,25 +88,22 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val) /*********************************************************************** * RX DDC Set **********************************************************************/ -void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) -{ +void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); boost::uint32_t reg_word = dsp_type1::calc_cordic_word_and_update( new_freq, _clock_ctrl->get_master_clock_freq()); - //TODO TODO TODO TODO TODO TODO TODO TODO TODO - // - // Handle multiple receive channels / DDC's - // - //TODO TODO TODO TODO TODO TODO TODO TODO TODO - _iface->poke32(FR_RX_FREQ_0, reg_word); - _iface->poke32(FR_RX_FREQ_1, reg_word); - _iface->poke32(FR_RX_FREQ_2, reg_word); - _iface->poke32(FR_RX_FREQ_3, reg_word); - - _rx_dsp_freq = new_freq; + static const uhd::dict + freq_name_to_reg_val = boost::assign::map_list_of + ("0", FR_RX_FREQ_0) ("1", FR_RX_FREQ_1) + ("2", FR_RX_FREQ_2) ("3", FR_RX_FREQ_3) + ; + _iface->poke32(freq_name_to_reg_val[key.name], reg_word); + _rx_dsp_freqs[key.name] = new_freq; return; } case DSP_PROP_HOST_RATE: { @@ -136,8 +145,9 @@ void usrp1_impl::tx_dsp_init(void) /*********************************************************************** * TX DUC Get **********************************************************************/ -void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val) -{ +void usrp1_impl::tx_dsp_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()) { case DSP_PROP_NAME: val = str(boost::format("usrp1 duc %uX %s") @@ -151,7 +161,16 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_FREQ_SHIFT: - val = _tx_dsp_freq; + val = _tx_dsp_freqs[key.name]; + return; + + case DSP_PROP_FREQ_SHIFT_NAMES:{ + prop_names_t names; + for(size_t i = 0; i < this->get_num_ducs(); i++){ + names.push_back(boost::lexical_cast(i)); + } + val = names; + } return; case DSP_PROP_CODEC_RATE: @@ -170,20 +189,20 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val) /*********************************************************************** * TX DUC Set **********************************************************************/ -void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) -{ +void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()) { - //TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO - // - // Set both codec frequencies until we have duality properties - // - //TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); - _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq); - _tx_dsp_freq = new_freq; + + //map the freq shift key to a subdev spec to a particular codec chip + std::string db_name = _tx_subdev_spec.at(boost::lexical_cast(key.name)).db_name; + if (db_name == "A") _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); + if (db_name == "B") _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq); + + _tx_dsp_freqs[key.name] = new_freq; return; } diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 464a82494..e55c3685b 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -36,6 +36,8 @@ using namespace uhd; using namespace uhd::usrp; +static const bool usrp1_mboard_verbose = false; + /*********************************************************************** * Calculate the RX mux value: * The I and Q mux values are intentionally reversed to flip I and Q @@ -220,15 +222,13 @@ void usrp1_impl::mboard_init(void) // Set default for TX format to 16-bit I&Q _iface->poke32(FR_TX_FORMAT, 0x00000000); - // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO - // - // Do something useful with the capabilities register - // - std::cout << "USRP1 Capabilities" << std::endl; - std::cout << " number of duc's: " << get_num_ddcs() << std::endl; - std::cout << " number of ddc's: " << get_num_ducs() << std::endl; - std::cout << " rx halfband: " << has_rx_halfband() << std::endl; - std::cout << " tx halfband: " << has_tx_halfband() << std::endl; + if (usrp1_mboard_verbose){ + std::cout << "USRP1 Capabilities" << std::endl; + std::cout << " number of duc's: " << get_num_ddcs() << std::endl; + std::cout << " number of ddc's: " << get_num_ducs() << std::endl; + std::cout << " rx halfband: " << has_rx_halfband() << std::endl; + std::cout << " tx halfband: " << has_tx_halfband() << std::endl; + } } void usrp1_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd) @@ -362,18 +362,26 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) case MBOARD_PROP_RX_SUBDEV_SPEC: _rx_subdev_spec = val.as(); + if (_rx_subdev_spec.size() > this->get_num_ddcs()){ + throw std::runtime_error(str(boost::format( + "USRP1 suports up to %u RX channels.\n" + "However, this RX subdev spec requires %u channels\n" + ) % this->get_num_ddcs() % _rx_subdev_spec.size())); + } verify_rx_subdev_spec(_rx_subdev_spec, _mboard_proxy->get_link()); - //sanity check - UHD_ASSERT_THROW(_rx_subdev_spec.size() <= 2); //set the mux and set the number of rx channels _iface->poke32(FR_RX_MUX, calc_rx_mux(_rx_subdev_spec, _mboard_proxy->get_link())); return; case MBOARD_PROP_TX_SUBDEV_SPEC: _tx_subdev_spec = val.as(); + if (_tx_subdev_spec.size() > this->get_num_ducs()){ + throw std::runtime_error(str(boost::format( + "USRP1 suports up to %u TX channels.\n" + "However, this TX subdev spec requires %u channels\n" + ) % this->get_num_ducs() % _tx_subdev_spec.size())); + } verify_tx_subdev_spec(_tx_subdev_spec, _mboard_proxy->get_link()); - //sanity check - UHD_ASSERT_THROW(_tx_subdev_spec.size() <= 2); //set the mux and set the number of tx channels _iface->poke32(FR_TX_MUX, calc_tx_mux(_tx_subdev_spec, _mboard_proxy->get_link())); return; diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 663fbb34b..f5e423654 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -179,14 +179,16 @@ private: void rx_dsp_init(void); void rx_dsp_get(const wax::obj &, wax::obj &); void rx_dsp_set(const wax::obj &, const wax::obj &); - double _rx_dsp_freq; size_t _rx_dsp_decim; + uhd::dict _rx_dsp_freqs; + size_t _rx_dsp_decim; wax_obj_proxy::sptr _rx_dsp_proxy; //tx dsp functions and settings void tx_dsp_init(void); void tx_dsp_get(const wax::obj &, wax::obj &); void tx_dsp_set(const wax::obj &, const wax::obj &); - double _tx_dsp_freq; size_t _tx_dsp_interp; + uhd::dict _tx_dsp_freqs; + size_t _tx_dsp_interp; wax_obj_proxy::sptr _tx_dsp_proxy; //transports diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp index 570f47293..1ef4af330 100644 --- a/host/test/tune_helper_test.cpp +++ b/host/test/tune_helper_test.cpp @@ -99,7 +99,8 @@ public: /* NOP */ } private: - void get(const wax::obj &key, wax::obj &val){ + void get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); switch(key.as()){ case DSP_PROP_CODEC_RATE: val = _codec_rate; @@ -109,11 +110,16 @@ private: val = _freq_shift; return; + case DSP_PROP_FREQ_SHIFT_NAMES: + val = prop_names_t(1, ""); + return; + default: UHD_THROW_PROP_GET_ERROR(); } } - void set(const wax::obj &key, const wax::obj &val){ + void set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); switch(key.as()){ case DSP_PROP_FREQ_SHIFT: _freq_shift = val.as(); @@ -136,12 +142,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){ dummy_dsp dsp(100e6); std::cout << "Testing tune helper RX automatic LO offset" << std::endl; - tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9); + tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, -100e3, tolerance); - double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); + double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance); } @@ -150,12 +156,12 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){ dummy_dsp dsp(100e6); std::cout << "Testing tune helper TX automatic LO offset" << std::endl; - tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9); + tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 100e3, tolerance); - double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); + double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance); } @@ -164,11 +170,11 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){ dummy_dsp dsp(100e6); std::cout << "Testing tune helper RX dummy basic board" << std::endl; - tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 55e6); + tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 55e6); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 0.0, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 45e6, tolerance); - double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); + double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance); } -- cgit v1.2.3 From 887aab36a0618124c3f2dffa8df9e8d943dfb1ee Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 20 Sep 2010 18:22:40 -0700 Subject: usrp2: make usrp2 dsp multi-channel compatible --- host/lib/usrp/usrp2/dsp_impl.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 6422142ce..0c85e643f 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -56,7 +56,9 @@ void usrp2_mboard_impl::init_ddc_config(void){ /*********************************************************************** * DDC Properties **********************************************************************/ -void usrp2_mboard_impl::ddc_get(const wax::obj &key, wax::obj &val){ +void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_NAME: val = std::string("usrp2 ddc0"); @@ -70,6 +72,10 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key, wax::obj &val){ val = _ddc_freq; return; + case DSP_PROP_FREQ_SHIFT_NAMES: + val = prop_names_t(1, ""); + return; + case DSP_PROP_CODEC_RATE: val = get_master_clock_freq(); return; @@ -82,7 +88,9 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key, wax::obj &val){ } } -void usrp2_mboard_impl::ddc_set(const wax::obj &key, const wax::obj &val){ +void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_FREQ_SHIFT:{ @@ -131,7 +139,9 @@ void usrp2_mboard_impl::init_duc_config(void){ /*********************************************************************** * DUC Properties **********************************************************************/ -void usrp2_mboard_impl::duc_get(const wax::obj &key, wax::obj &val){ +void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_NAME: val = std::string("usrp2 duc0"); @@ -145,6 +155,10 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key, wax::obj &val){ val = _duc_freq; return; + case DSP_PROP_FREQ_SHIFT_NAMES: + val = prop_names_t(1, ""); + return; + case DSP_PROP_CODEC_RATE: val = get_master_clock_freq(); return; @@ -157,7 +171,9 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key, wax::obj &val){ } } -void usrp2_mboard_impl::duc_set(const wax::obj &key, const wax::obj &val){ +void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + switch(key.as()){ case DSP_PROP_FREQ_SHIFT:{ -- cgit v1.2.3 From 000578892e9cf8f0117b55dc5d770faad36740d0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 22 Sep 2010 17:36:18 -0700 Subject: usrp1: reworked the io_impl for usrp1 to use the vrt packet handler used dummy packers and unpackets that have a header size of zero created wrapper around the data transport to handle non-512 multiple sends honor the eob flag on send to flush the send buffer --- host/lib/usrp/simple_usrp.cpp | 2 +- host/lib/usrp/usrp1/io_impl.cpp | 476 ++++++++++++++++++------------------- host/lib/usrp/usrp1/usrp1_impl.hpp | 12 +- host/lib/usrp/usrp2/io_impl.cpp | 2 +- 4 files changed, 242 insertions(+), 250 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index d29952955..b89b76eed 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -216,7 +216,7 @@ simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ "The simple USRP interface has been deprecated.\n" "Please switch to the single USRP interface.\n" "#include \n" - "simple_usrp::sptr sdev = simple_usrp::make(args);\n" + "single_usrp::sptr sdev = single_usrp::make(args);\n" ); return sptr(new simple_usrp_impl(dev_addr)); } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 92e8bc20a..7446c7f7c 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,294 +33,278 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -struct usrp1_send_state { - uhd::transport::managed_send_buffer::sptr send_buff; - size_t bytes_written; - size_t underrun_poll_samp_count; - - size_t bytes_free() +/*********************************************************************** + * 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) { - if (send_buff != NULL) - return send_buff->size() - bytes_written; - else - return 0; + /* NOP */ } -}; -struct usrp1_recv_state { - uhd::transport::managed_recv_buffer::sptr recv_buff; - size_t bytes_read; - size_t overrun_poll_samp_count; + ssize_t commit(size_t num_bytes){ + return _commit(num_bytes); + } - size_t bytes_avail() - { - if (recv_buff != NULL) - return recv_buff->size() - bytes_read; - else - return 0; +private: + const boost::asio::mutable_buffer &get(void) const{ + return _buff; } -}; -/*********************************************************************** - * IO Implementation Details - **********************************************************************/ -struct usrp1_impl::io_impl { - io_impl(); - ~io_impl(void); - - //state handling for buffer management - usrp1_recv_state recv_state; - usrp1_send_state send_state; - - //send transport management - bool get_send_buffer(zero_copy_if::sptr zc_if); - size_t copy_convert_send_samps(const void *buff, size_t num_samps, - size_t sample_offset, const io_type_t io_type, - otw_type_t otw_type); - bool conditional_buff_commit(bool force); - bool check_underrun(usrp_ctrl::sptr ctrl_if, - size_t poll_interval, bool force); - - //recv transport management - bool get_recv_buffer(zero_copy_if::sptr zc_if); - size_t copy_convert_recv_samps(void *buff, size_t num_samps, - size_t sample_offset, const io_type_t io_type, - otw_type_t otw_type); - bool check_overrun(usrp_ctrl::sptr ctrl_if, - size_t poll_interval, bool force); + const boost::asio::mutable_buffer _buff; + const boost::function _commit; }; -usrp1_impl::io_impl::io_impl() -{ - send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); - recv_state.recv_buff = uhd::transport::managed_recv_buffer::sptr(); -} - -usrp1_impl::io_impl::~io_impl(void) -{ - /* NOP */ -} - -void usrp1_impl::io_init(void) -{ - _rx_otw_type.width = 16; - _rx_otw_type.shift = 0; - _rx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - - _io_impl = UHD_PIMPL_MAKE(io_impl, ()); -} - /*********************************************************************** - * Data Send + * IO Implementation Details **********************************************************************/ -bool usrp1_impl::io_impl::get_send_buffer(zero_copy_if::sptr zc_if) -{ - if (send_state.send_buff == NULL) { +struct usrp1_impl::io_impl{ + io_impl(zero_copy_if::sptr data_transport): + data_transport(data_transport), + underflow_poll_samp_count(0), + overflow_poll_samp_count(0), + send_buff(data_transport->get_send_buff()), + num_bytes_committed(0) + { + /* NOP */ + } - send_state.send_buff = zc_if->get_send_buff(); - if (send_state.send_buff == NULL) - return false; + ~io_impl(void){ + flush_send_buff(); + } - send_state.bytes_written = 0; + zero_copy_if::sptr data_transport; + + //state management for the vrt packet handler code + vrt_packet_handler::recv_state packet_handler_recv_state; + vrt_packet_handler::send_state packet_handler_send_state; + + //state management for overflow and underflow + size_t underflow_poll_samp_count; + size_t overflow_poll_samp_count; + + //wrapper around the actual send buffer interface + //all of this to ensure only full buffers are committed + managed_send_buffer::sptr send_buff; + size_t num_bytes_committed; + 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 &); + + //helpers to get at the send buffer + offset + inline void *get_send_mem_ptr(void){ + return send_buff->cast() + num_bytes_committed; + } + inline size_t get_send_mem_size(void){ + return send_buff->size() - num_bytes_committed; } +}; - return true; +/*! + * Accept a commit of num bytes to the pseudo buffer. + * Memcpy the entire contents of pseudo buffer into send buffers. + * + * Under most conditions: + * 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){ + 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; + } + return bytes_copied; } -size_t usrp1_impl::io_impl::copy_convert_send_samps(const void *buff, - size_t num_samps, - size_t sample_offset, - const io_type_t io_type, - otw_type_t otw_type) -{ - UHD_ASSERT_THROW(send_state.bytes_free() % otw_type.get_sample_size() == 0); - - size_t samps_free = send_state.bytes_free() / otw_type.get_sample_size(); - size_t copy_samps = std::min(num_samps - sample_offset, samps_free); - - const boost::uint8_t *io_mem = - reinterpret_cast(buff); - - boost::uint8_t *otw_mem = send_state.send_buff->cast(); - - convert_io_type_to_otw_type(io_mem + sample_offset * io_type.size, - io_type, - otw_mem + send_state.bytes_written, - otw_type, - copy_samps); - - send_state.bytes_written += copy_samps * otw_type.get_sample_size(); - send_state.underrun_poll_samp_count += copy_samps; - - return copy_samps; +/*! + * 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){ + 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; } -bool usrp1_impl::io_impl::conditional_buff_commit(bool force) -{ - if (send_state.bytes_written % 512) - return false; - - if (force || send_state.bytes_free() == 0) { - send_state.send_buff->commit(send_state.bytes_written); - send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); - return true; - } - - return false; +/*! + * Flush the send buffer: + * Zero-pad the send buffer to the nearest 512 byte boundary and commit. + */ +void usrp1_impl::io_impl::flush_send_buff(void){ + size_t bytes_to_pad = (-1*num_bytes_committed)%512; + std::memset(get_send_mem_ptr(), 0, bytes_to_pad); + num_bytes_committed += bytes_to_pad; + commit_send_buff(); } -bool usrp1_impl::io_impl::check_underrun(usrp_ctrl::sptr ctrl_if, - size_t poll_interval, - bool force) -{ - unsigned char underrun = 0; - - bool ready_to_poll = send_state.underrun_poll_samp_count > poll_interval; - - if (force || ready_to_poll) { - int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, - 0, - GS_TX_UNDERRUN, - &underrun, sizeof(char)); - if (ret < 0) - std::cerr << "USRP: underrun check failed" << std::endl; - if (underrun) - std::cerr << "U" << std::flush; - - send_state.underrun_poll_samp_count = 0; - } - - return (bool) underrun; +/*! + * 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); + send_buff = data_transport->get_send_buff(); + num_bytes_committed = 0; + return ret; } -size_t usrp1_impl::send(const std::vector &buffs, - size_t num_samps, - const tx_metadata_t &, - const io_type_t &io_type, - send_mode_t) -{ +bool usrp1_impl::io_impl::get_send_buffs( + vrt_packet_handler::managed_send_buffs_t &buffs +){ UHD_ASSERT_THROW(buffs.size() == 1); - size_t total_samps_sent = 0; - - while (total_samps_sent < num_samps) { - if (!_io_impl->get_send_buffer(_data_transport)) - return 0; - - total_samps_sent += _io_impl->copy_convert_send_samps(buffs[0], - num_samps, - total_samps_sent, - io_type, - _tx_otw_type); - if (total_samps_sent == num_samps) - _io_impl->conditional_buff_commit(true); - else - _io_impl->conditional_buff_commit(false); - - _io_impl->check_underrun(_ctrl_transport, - _tx_samps_per_poll_interval, false); + //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( + 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( + boost::asio::buffer(get_send_mem_ptr(), get_send_mem_size()), + boost::bind(&usrp1_impl::io_impl::phony_commit_send_buff, this, _1) + )); } - return total_samps_sent; + return buffs[0].get(); } /*********************************************************************** - * Data Recv + * Initialize internals within this file **********************************************************************/ -bool usrp1_impl::io_impl::get_recv_buffer(zero_copy_if::sptr zc_if) -{ - if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail() == 0)) { - - recv_state.recv_buff = zc_if->get_recv_buff(); - if (recv_state.recv_buff == NULL) - return false; +void usrp1_impl::io_init(void){ + _rx_otw_type.width = 16; + _rx_otw_type.shift = 0; + _rx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - recv_state.bytes_read = 0; - } + _tx_otw_type.width = 16; + _tx_otw_type.shift = 0; + _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - return true; + _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); } -size_t usrp1_impl::io_impl::copy_convert_recv_samps(void *buff, - size_t num_samps, - size_t sample_offset, - const io_type_t io_type, - otw_type_t otw_type) -{ - UHD_ASSERT_THROW(recv_state.bytes_avail() % otw_type.get_sample_size() == 0); - - size_t samps_avail = recv_state.bytes_avail() / otw_type.get_sample_size(); - size_t copy_samps = std::min(num_samps - sample_offset, samps_avail); - - const boost::uint8_t *otw_mem = - recv_state.recv_buff->cast(); - - boost::uint8_t *io_mem = reinterpret_cast(buff); - - convert_otw_type_to_io_type(otw_mem + recv_state.bytes_read, - otw_type, - io_mem + sample_offset * io_type.size, - io_type, - copy_samps); - - recv_state.bytes_read += copy_samps * otw_type.get_sample_size(); - recv_state.overrun_poll_samp_count += copy_samps; - - return copy_samps; +/*********************************************************************** + * Data send + helper functions + **********************************************************************/ +static void usrp1_bs_vrt_packer( + boost::uint32_t *, + vrt::if_packet_info_t &if_packet_info +){ + if_packet_info.num_header_words32 = 0; + if_packet_info.num_packet_words32 = if_packet_info.num_payload_words32; } -bool usrp1_impl::io_impl::check_overrun(usrp_ctrl::sptr ctrl_if, - size_t poll_interval, - bool force) -{ - unsigned char overrun = 0; - - bool ready_to_poll = recv_state.overrun_poll_samp_count > poll_interval; - - if (force || ready_to_poll) { - int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, - 0, - GS_RX_OVERRUN, - &overrun, sizeof(char)); - if (ret < 0) - std::cerr << "USRP: overrrun check failed" << std::endl; - if (overrun) - std::cerr << "O" << std::flush; - - recv_state.overrun_poll_samp_count = 0; +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 +){ + size_t num_samps_sent = vrt_packet_handler::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, _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), + get_max_send_samps_per_packet() + ); + + //Don't honor sob because it is normal to be always bursting... + //handle eob flag (commit the buffer) + if (metadata.end_of_burst) _io_impl->flush_send_buff(); + + //handle the polling for underflow conditions + _io_impl->underflow_poll_samp_count += num_samps_sent; + if (_io_impl->underflow_poll_samp_count >= _tx_samps_per_poll_interval){ + _io_impl->underflow_poll_samp_count = 0; //reset count + boost::uint8_t underflow = 0; + ssize_t ret = _ctrl_transport->usrp_control_read( + VRQ_GET_STATUS, 0, GS_TX_UNDERRUN, + &underflow, sizeof(underflow) + ); + if (ret < 0) std::cerr << "USRP: underflow check failed" << std::endl; + else if (underflow) std::cerr << "U" << std::flush; } - return (bool) overrun; + return num_samps_sent; } -size_t usrp1_impl::recv(const std::vector &buffs, - size_t num_samps, - rx_metadata_t &, - const io_type_t &io_type, - recv_mode_t, - size_t) -{ - UHD_ASSERT_THROW(buffs.size() == 1); - - size_t total_samps_recv = 0; - - while (total_samps_recv < num_samps) { +/*********************************************************************** + * Data recv + helper functions + **********************************************************************/ +static void usrp1_bs_vrt_unpacker( + const boost::uint32_t *, + vrt::if_packet_info_t &if_packet_info +){ + if_packet_info.packet_type = vrt::if_packet_info_t::PACKET_TYPE_DATA; + if_packet_info.num_payload_words32 = if_packet_info.num_packet_words32; + if_packet_info.num_header_words32 = 0; + if_packet_info.packet_count = 0; + if_packet_info.sob = false; + if_packet_info.eob = false; + if_packet_info.has_sid = false; + if_packet_info.has_cid = false; + if_packet_info.has_tsi = false; + if_packet_info.has_tsf = false; + if_packet_info.has_tlr = false; +} - if (!_io_impl->get_recv_buffer(_data_transport)) - return 0; +static bool get_recv_buffs( + zero_copy_if::sptr zc_if, + vrt_packet_handler::managed_recv_buffs_t &buffs +){ + UHD_ASSERT_THROW(buffs.size() == 1); + buffs[0] = zc_if->get_recv_buff(); + return buffs[0].get(); +} - total_samps_recv += _io_impl->copy_convert_recv_samps(buffs[0], - num_samps, - total_samps_recv, - io_type, - _rx_otw_type); - _io_impl->check_overrun(_ctrl_transport, - _rx_samps_per_poll_interval, false); +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*/ +){ + size_t num_samps_recvd = vrt_packet_handler::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, _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) + ); + + //handle the polling for overflow conditions + _io_impl->overflow_poll_samp_count += num_samps_recvd; + if (_io_impl->overflow_poll_samp_count >= _rx_samps_per_poll_interval){ + _io_impl->overflow_poll_samp_count = 0; //reset count + boost::uint8_t overflow = 0; + ssize_t ret = _ctrl_transport->usrp_control_read( + VRQ_GET_STATUS, 0, GS_RX_OVERRUN, + &overflow, sizeof(overflow) + ); + if (ret < 0) std::cerr << "USRP: overflow check failed" << std::endl; + else if (overflow) std::cerr << "O" << std::flush; } - return total_samps_recv; + return num_samps_recvd; } diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index f5e423654..3ea35f970 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -91,8 +91,16 @@ public: recv_mode_t, size_t timeout); - size_t get_max_send_samps_per_packet(void) const { return 0; } - size_t get_max_recv_samps_per_packet(void) const { return 0; } + static const size_t BYTES_PER_PACKET = 512*4; //under the transfer size + + size_t get_max_send_samps_per_packet(void) const { + return BYTES_PER_PACKET/_tx_otw_type.get_sample_size(); + } + + size_t get_max_recv_samps_per_packet(void) const { + return BYTES_PER_PACKET/_rx_otw_type.get_sample_size(); + } + bool recv_async_msg(uhd::async_metadata_t &, size_t); private: diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 4e883cf81..91a1b2344 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -189,7 +189,7 @@ bool usrp2_impl::recv_async_msg( /*********************************************************************** * Send Data **********************************************************************/ -bool get_send_buffs( +static bool get_send_buffs( const std::vector &trans, vrt_packet_handler::managed_send_buffs_t &buffs ){ -- cgit v1.2.3 From 7ee585f2b9f74a3732e364095f7e5b8f18ae3595 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 22 Sep 2010 19:14:57 -0700 Subject: usrp1: multi-channel rx working, modified vrt handler to deinterleave --- host/lib/transport/gen_convert_types.py | 10 +++++----- host/lib/transport/vrt_packet_handler.hpp | 30 ++++++++++++++++++++---------- host/lib/usrp/usrp1/io_impl.cpp | 5 ++++- 3 files changed, 29 insertions(+), 16 deletions(-) (limited to 'host/lib') diff --git a/host/lib/transport/gen_convert_types.py b/host/lib/transport/gen_convert_types.py index adbd22868..f9509c81d 100755 --- a/host/lib/transport/gen_convert_types.py +++ b/host/lib/transport/gen_convert_types.py @@ -99,9 +99,9 @@ void transport::convert_io_type_to_otw_type( nsamps_per_io_buff ); #else - for (size_t i = 0; i < nsamps_per_io_buff; i++){ + for (size_t i = 0, j = 0; i < nsamps_per_io_buff; i++){ #for $j in range($num_chans) - reinterpret_cast<$(out_type)_t *>(otw_buff)[i*$num_chans + $j] = + reinterpret_cast<$(out_type)_t *>(otw_buff)[j++] = #if $ph.get_swap_type($pred) == 'bswap' uhd::byteswap($(converter)(reinterpret_cast(io_buffs[$j])[i])); #else @@ -139,13 +139,13 @@ void transport::convert_otw_type_to_io_type( nsamps_per_io_buff ); #else - for (size_t i = 0; i < nsamps_per_io_buff; i++){ + for (size_t i = 0, j = 0; i < nsamps_per_io_buff; i++){ #for $j in range($num_chans) reinterpret_cast<$(out_type)_t *>(io_buffs[$j])[i] = #if $ph.get_swap_type($pred) == 'bswap' - $(converter)(uhd::byteswap(reinterpret_cast(otw_buff)[i*$num_chans + $j])); + $(converter)(uhd::byteswap(reinterpret_cast(otw_buff)[j++])); #else - $(converter)(reinterpret_cast(otw_buff)[i*$num_chans + $j]); + $(converter)(reinterpret_cast(otw_buff)[j++]); #end if #end for } diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 7e0588f03..596989951 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -150,7 +150,8 @@ template UHD_INLINE T get_context_code( const vrt_unpacker_t &vrt_unpacker, const get_recv_buffs_t &get_recv_buffs, const handle_overflow_t &handle_overflow, - size_t vrt_header_offset_words32 + size_t vrt_header_offset_words32, + size_t chans_per_otw_buff ){ metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_NONE; @@ -184,15 +185,21 @@ template UHD_INLINE T get_context_code( //extract the number of samples available to copy size_t bytes_per_item = otw_type.get_sample_size(); size_t nsamps_available = state.size_of_copy_buffs/bytes_per_item; - size_t nsamps_to_copy = std::min(total_samps, nsamps_available); + size_t nsamps_to_copy = std::min(total_samps*chans_per_otw_buff, nsamps_available); size_t bytes_to_copy = nsamps_to_copy*bytes_per_item; + size_t nsamps_to_copy_per_io_buff = nsamps_to_copy/chans_per_otw_buff; + + std::vector io_buffs(chans_per_otw_buff); + for (size_t i = 0; i < state.width; i+=chans_per_otw_buff){ + + //fill a vector with pointers to the io buffers + for (size_t j = 0; j < chans_per_otw_buff; j++){ + io_buffs[j] = reinterpret_cast(buffs[i+j]) + offset_bytes; + } - for (size_t i = 0; i < state.width; i++){ //copy-convert the samples from the recv buffer uhd::transport::convert_otw_type_to_io_type( - state.copy_buffs[i], otw_type, - reinterpret_cast(buffs[i]) + offset_bytes, - io_type, nsamps_to_copy + state.copy_buffs[i], otw_type, io_buffs, io_type, nsamps_to_copy_per_io_buff ); //update the rx copy buffer to reflect the bytes copied @@ -206,7 +213,7 @@ template UHD_INLINE T get_context_code( metadata.fragment_offset = state.fragment_offset_in_samps; state.fragment_offset_in_samps += nsamps_to_copy; //set for next call - return nsamps_to_copy; + return nsamps_to_copy_per_io_buff; } /******************************************************************* @@ -224,7 +231,8 @@ template UHD_INLINE T get_context_code( const vrt_unpacker_t &vrt_unpacker, const get_recv_buffs_t &get_recv_buffs, const handle_overflow_t &handle_overflow = &handle_overflow_nop, - size_t vrt_header_offset_words32 = 0 + size_t vrt_header_offset_words32 = 0, + size_t chans_per_otw_buff = 1 ){ switch(recv_mode){ @@ -241,7 +249,8 @@ template UHD_INLINE T get_context_code( vrt_unpacker, get_recv_buffs, handle_overflow, - vrt_header_offset_words32 + vrt_header_offset_words32, + chans_per_otw_buff ); } @@ -261,7 +270,8 @@ template UHD_INLINE T get_context_code( vrt_unpacker, get_recv_buffs, handle_overflow, - vrt_header_offset_words32 + vrt_header_offset_words32, + chans_per_otw_buff ); if (num_samps == 0) break; //had a recv timeout or error, break loop accum_num_samps += num_samps; diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 7446c7f7c..a813a0462 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -290,7 +290,10 @@ 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, _1), + &vrt_packet_handler::handle_overflow_nop, + 0, //vrt header offset + _rx_subdev_spec.size() //num channels ); //handle the polling for overflow conditions -- cgit v1.2.3 From c36b8a83b1b510a0a8bc6e5600a537cbedea8f30 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 23 Sep 2010 12:37:11 -0700 Subject: usrp1: multi-channel tx working, modified vrt handler to interleave --- host/lib/transport/vrt_packet_handler.hpp | 28 +++++++++++++++++----------- host/lib/usrp/usrp1/io_impl.cpp | 4 +++- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 ++-- 3 files changed, 22 insertions(+), 14 deletions(-) (limited to 'host/lib') diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 596989951..b603f1371 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -313,29 +313,32 @@ template UHD_INLINE T get_context_code( 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 vrt_header_offset_words32, + size_t chans_per_otw_buff ){ //load the rest of the if_packet_info in here - if_packet_info.num_payload_words32 = (num_samps*otw_type.get_sample_size())/sizeof(boost::uint32_t); + if_packet_info.num_payload_words32 = (num_samps*chans_per_otw_buff*otw_type.get_sample_size())/sizeof(boost::uint32_t); if_packet_info.packet_count = state.next_packet_seq++; //get send buffers for each channel - managed_send_buffs_t send_buffs(buffs.size()); + managed_send_buffs_t send_buffs(buffs.size()/chans_per_otw_buff); UHD_ASSERT_THROW(get_send_buffs(send_buffs)); - for (size_t i = 0; i < buffs.size(); i++){ + std::vector io_buffs(chans_per_otw_buff); + for (size_t i = 0; i < buffs.size(); i+=chans_per_otw_buff){ //calculate pointers with offsets to io and otw memory - const boost::uint8_t *io_mem = reinterpret_cast(buffs[i]) + offset_bytes; + for (size_t j = 0; j < chans_per_otw_buff; j++){ + io_buffs[j] = reinterpret_cast(buffs[i+j]) + offset_bytes; + } boost::uint32_t *otw_mem = send_buffs[i]->cast() + vrt_header_offset_words32; //pack metadata into a vrt header vrt_packer(otw_mem, if_packet_info); + otw_mem += if_packet_info.num_header_words32; //copy-convert the samples into the send buffer uhd::transport::convert_io_type_to_otw_type( - io_mem, io_type, - otw_mem + if_packet_info.num_header_words32, otw_type, - num_samps + io_buffs, io_type, otw_mem, otw_type, num_samps ); //commit the samples to the zero-copy interface @@ -361,7 +364,8 @@ template UHD_INLINE T get_context_code( const vrt_packer_t &vrt_packer, const get_send_buffs_t &get_send_buffs, size_t max_samples_per_packet, - size_t vrt_header_offset_words32 = 0 + size_t vrt_header_offset_words32 = 0, + size_t chans_per_otw_buff = 1 ){ //translate the metadata to vrt if packet info uhd::transport::vrt::if_packet_info_t if_packet_info; @@ -393,7 +397,8 @@ template UHD_INLINE T get_context_code( io_type, otw_type, vrt_packer, get_send_buffs, - vrt_header_offset_words32 + vrt_header_offset_words32, + chans_per_otw_buff ); return num_samps; } @@ -424,7 +429,8 @@ template UHD_INLINE T get_context_code( io_type, otw_type, vrt_packer, get_send_buffs, - vrt_header_offset_words32 + vrt_header_offset_words32, + chans_per_otw_buff ); } return total_num_samps; diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index a813a0462..146038bd9 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -226,7 +226,9 @@ size_t usrp1_impl::send( _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), - get_max_send_samps_per_packet() + get_max_send_samps_per_packet(), + 0, //vrt header offset + _tx_subdev_spec.size() //num channels ); //Don't honor sob because it is normal to be always bursting... diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 3ea35f970..20ae3c02a 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -94,11 +94,11 @@ public: static const size_t BYTES_PER_PACKET = 512*4; //under the transfer size size_t get_max_send_samps_per_packet(void) const { - return BYTES_PER_PACKET/_tx_otw_type.get_sample_size(); + return BYTES_PER_PACKET/_tx_otw_type.get_sample_size()/_tx_subdev_spec.size(); } size_t get_max_recv_samps_per_packet(void) const { - return BYTES_PER_PACKET/_rx_otw_type.get_sample_size(); + return BYTES_PER_PACKET/_rx_otw_type.get_sample_size()/_rx_subdev_spec.size(); } bool recv_async_msg(uhd::async_metadata_t &, size_t); -- cgit v1.2.3 From fbcd677284685e666556f396745ec570b01ea830 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 23 Sep 2010 12:47:46 -0700 Subject: usrp1: sanity check, only 1 channel per tx slot --- host/lib/usrp/usrp1/mboard_impl.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index e55c3685b..fe3774eb4 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -148,6 +148,7 @@ static boost::uint32_t calc_tx_mux( //calculate the channel flags int channel_flags = 0, chan = 0; + uhd::dict slot_to_chan_count = boost::assign::map_list_of("A", 0)("B", 0); BOOST_FOREACH(const subdev_spec_pair_t &pair, subdev_spec){ wax::obj dboard = mboard[named_prop_t(MBOARD_PROP_TX_DBOARD, pair.db_name)]; wax::obj subdev = dboard[named_prop_t(DBOARD_PROP_SUBDEV, pair.sd_name)]; @@ -157,6 +158,14 @@ static boost::uint32_t calc_tx_mux( if (pair.db_name == "A") channel_flags |= chan_to_conn_to_flag[chan][conn] << 0; if (pair.db_name == "B") channel_flags |= chan_to_conn_to_flag[chan][conn] << 8; + //sanity check, only 1 channel per slot + slot_to_chan_count[pair.db_name]++; + if (slot_to_chan_count[pair.db_name] > 1){ + throw std::runtime_error(str(boost::format( + "dboard slot %s assigned to multiple channels in subdev spec %s" + ) % pair.db_name % subdev_spec.to_string())); + } + //increment for the next channel chan++; } -- cgit v1.2.3 From 24bcc7d7644621bd18a998b23cd91b086b87ea90 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 23 Sep 2010 12:58:40 -0700 Subject: basic: added the 4th BA subdevice to basic and lf dboard code --- host/docs/dboards.rst | 10 ++++++---- host/lib/usrp/dboard/db_basic_and_lf.cpp | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'host/lib') diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 985fbc12b..738a0696d 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -15,11 +15,12 @@ properties of each board as well. ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Basic RX and and LFRX ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The Basic RX and LFRX boards have 3 subdevices: +The Basic RX and LFRX boards have 4 subdevices: * **Subdevice A:** real signal on antenna RXA * **Subdevice B:** real signal on antenna RXB -* **Subdevice AB:** quadrature subdevice using both antennas +* **Subdevice AB:** quadrature subdevice using both antennas (IQ) +* **Subdevice BA:** quadrature subdevice using both antennas (QI) The boards have no tunable elements or programmable gains. Though the magic of aliasing, you can down-convert signals @@ -28,11 +29,12 @@ greater than the Nyquist rate of the ADC. ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Basic TX and and LFTX ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The Basic TX and LFTX boards have 3 subdevices: +The Basic TX and LFTX boards have 4 subdevices: * **Subdevice A:** real signal on antenna TXA * **Subdevice B:** real signal on antenna TXB -* **Subdevice AB:** quadrature subdevice using both antennas +* **Subdevice AB:** quadrature subdevice using both antennas (IQ) +* **Subdevice BA:** quadrature subdevice using both antennas (QI) The boards have no tunable elements or programmable gains. Though the magic of aliasing, you can up-convert signals diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 2a9bf2ca5..4b0d8bf27 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -59,6 +59,7 @@ private: static const uhd::dict sd_name_to_conn = map_list_of ("AB", SUBDEV_CONN_COMPLEX_IQ) + ("BA", SUBDEV_CONN_COMPLEX_QI) ("A", SUBDEV_CONN_REAL_I) ("B", SUBDEV_CONN_REAL_Q) ; -- cgit v1.2.3 From ea82d5fe9a9cde24409c528160e6ba6f3bced41b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 23 Sep 2010 15:42:55 -0700 Subject: libusb: various minor code tweaks --- host/include/uhd/transport/usb_device_handle.hpp | 12 ++++++------ host/include/uhd/transport/usb_zero_copy.hpp | 2 +- host/lib/transport/CMakeLists.txt | 1 + host/lib/transport/libusb1_base.hpp | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) (limited to 'host/lib') diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index c3eb72b00..735a3acbe 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 UHD_API usb_device_handle : boost::noncopyable { +class usb_device_handle : boost::noncopyable { public: typedef boost::shared_ptr sptr; @@ -46,31 +46,31 @@ public: * Return the device's serial number * \return a string describing the device's serial number */ - virtual UHD_API std::string get_serial() const = 0; + virtual std::string get_serial() const = 0; /*! * Return the device's Vendor ID (usually assigned by the USB-IF) * \return a Vendor ID */ - virtual UHD_API boost::uint16_t get_vendor_id() const = 0; + virtual boost::uint16_t get_vendor_id() const = 0; /*! * Return the device's Product ID (usually assigned by manufacturer) * \return a Product ID */ - virtual UHD_API boost::uint16_t get_product_id() const = 0; + virtual boost::uint16_t get_product_id() const = 0; /*! * Return the device's USB address * \return a Product ID */ - virtual UHD_API boost::uint16_t get_device_addr() const = 0; + 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 */ - static UHD_API std::vector get_device_list(boost::uint16_t vid, boost::uint16_t pid); + static std::vector get_device_list(boost::uint16_t vid, boost::uint16_t pid); }; //namespace usb diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp index 2edd6d91d..75232c22a 100644 --- a/host/include/uhd/transport/usb_zero_copy.hpp +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -53,7 +53,7 @@ public: static sptr make(usb_device_handle::sptr handle, unsigned int rx_endpoint, unsigned int tx_endpoint, - size_t buff_size = 0, + size_t buff_size = 0, size_t block_size = 0); }; diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 71a3a1494..acd699fc5 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -30,6 +30,7 @@ IF(LIBUSB_FOUND) ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_control.cpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_zero_copy.cpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.cpp + ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.hpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp ) SET(HAVE_USB_SUPPORT TRUE) diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index abe5e22a2..484bcf3d9 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#ifndef INCLUDED_TRANSPORT_LIBUSB_HPP -#define INCLUDED_TRANSPORT_LIBUSB_HPP +#ifndef INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP +#define INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP #include #include @@ -91,4 +91,4 @@ namespace libusb { }} //namespace -#endif /* INCLUDED_TRANSPORT_LIBUSB_HPP */ +#endif /* INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP */ -- cgit v1.2.3 From 1826421cd428f795b4b8cd0acdad4fea92262f72 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 23 Sep 2010 15:42:55 -0700 Subject: libusb: various minor code tweaks --- host/include/uhd/transport/usb_device_handle.hpp | 12 ++++++------ host/include/uhd/transport/usb_zero_copy.hpp | 2 +- host/lib/transport/CMakeLists.txt | 1 + host/lib/transport/libusb1_base.hpp | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) (limited to 'host/lib') diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index c3eb72b00..735a3acbe 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 UHD_API usb_device_handle : boost::noncopyable { +class usb_device_handle : boost::noncopyable { public: typedef boost::shared_ptr sptr; @@ -46,31 +46,31 @@ public: * Return the device's serial number * \return a string describing the device's serial number */ - virtual UHD_API std::string get_serial() const = 0; + virtual std::string get_serial() const = 0; /*! * Return the device's Vendor ID (usually assigned by the USB-IF) * \return a Vendor ID */ - virtual UHD_API boost::uint16_t get_vendor_id() const = 0; + virtual boost::uint16_t get_vendor_id() const = 0; /*! * Return the device's Product ID (usually assigned by manufacturer) * \return a Product ID */ - virtual UHD_API boost::uint16_t get_product_id() const = 0; + virtual boost::uint16_t get_product_id() const = 0; /*! * Return the device's USB address * \return a Product ID */ - virtual UHD_API boost::uint16_t get_device_addr() const = 0; + 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 */ - static UHD_API std::vector get_device_list(boost::uint16_t vid, boost::uint16_t pid); + static std::vector get_device_list(boost::uint16_t vid, boost::uint16_t pid); }; //namespace usb diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp index 2edd6d91d..75232c22a 100644 --- a/host/include/uhd/transport/usb_zero_copy.hpp +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -53,7 +53,7 @@ public: static sptr make(usb_device_handle::sptr handle, unsigned int rx_endpoint, unsigned int tx_endpoint, - size_t buff_size = 0, + size_t buff_size = 0, size_t block_size = 0); }; diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 71a3a1494..acd699fc5 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -30,6 +30,7 @@ IF(LIBUSB_FOUND) ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_control.cpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_zero_copy.cpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.cpp + ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.hpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp ) SET(HAVE_USB_SUPPORT TRUE) diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index abe5e22a2..484bcf3d9 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#ifndef INCLUDED_TRANSPORT_LIBUSB_HPP -#define INCLUDED_TRANSPORT_LIBUSB_HPP +#ifndef INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP +#define INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP #include #include @@ -91,4 +91,4 @@ namespace libusb { }} //namespace -#endif /* INCLUDED_TRANSPORT_LIBUSB_HPP */ +#endif /* INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP */ -- cgit v1.2.3 From f97c4338458a965502d73903983ae5a3ceeebd53 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 23 Sep 2010 18:07:31 -0700 Subject: usrp1: fixes to remove warnings and errors for usrp1 + libusb windows --- host/lib/transport/CMakeLists.txt | 3 +++ host/lib/transport/include/stdint.h | 35 ++++++++++++++++++++++++++++ host/lib/transport/libusb1_base.cpp | 2 +- host/lib/transport/libusb1_device_handle.cpp | 18 +++++++------- host/lib/transport/libusb1_zero_copy.cpp | 3 +-- host/lib/usrp/usrp1/codec_ctrl.cpp | 4 ++-- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 4 ++-- host/lib/usrp/usrp1/usrp1_iface.cpp | 4 ++-- host/lib/usrp/usrp1/usrp1_impl.cpp | 2 +- 9 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 host/lib/transport/include/stdint.h (limited to 'host/lib') diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index acd699fc5..92c9f3181 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -33,6 +33,9 @@ IF(LIBUSB_FOUND) ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.hpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp ) + IF(WIN32) #include our custom stdint for libusb + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/include) + ENDIF(WIN32) SET(HAVE_USB_SUPPORT TRUE) ENDIF(LIBUSB_FOUND) diff --git a/host/lib/transport/include/stdint.h b/host/lib/transport/include/stdint.h new file mode 100644 index 000000000..b3eb61aae --- /dev/null +++ b/host/lib/transport/include/stdint.h @@ -0,0 +1,35 @@ +// +// 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_LIBUHD_TRANSPORT_STDINT_H +#define INCLUDED_LIBUHD_TRANSPORT_STDINT_H + +#include + +//provide a stdint implementation for libusb + +typedef boost::uint64_t uint64_t; +typedef boost::uint32_t uint32_t; +typedef boost::uint16_t uint16_t; +typedef boost::uint8_t uint8_t; + +typedef boost::int64_t int64_t; +typedef boost::int32_t int32_t; +typedef boost::int16_t int16_t; +typedef boost::int8_t int8_t; + +#endif /* INCLUDED_LIBUHD_TRANSPORT_STDINT_H */ diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index e21c39aa3..1f816c6e2 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -67,7 +67,7 @@ bool libusb::compare_device(libusb_device *dev, std::string serial = handle->get_serial(); boost::uint16_t vendor_id = handle->get_vendor_id(); boost::uint16_t product_id = handle->get_product_id(); - boost::uint8_t device_addr = handle->get_device_addr(); + boost::uint16_t device_addr = handle->get_device_addr(); libusb_device_descriptor libusb_desc; if (libusb_get_device_descriptor(dev, &libusb_desc) < 0) diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp index 43d0f0e26..7efddd410 100644 --- a/host/lib/transport/libusb1_device_handle.cpp +++ b/host/lib/transport/libusb1_device_handle.cpp @@ -29,9 +29,9 @@ const int libusb_debug_level = 0; class libusb1_device_handle_impl : public usb_device_handle { public: libusb1_device_handle_impl(std::string serial, - boost::uint32_t product_id, - boost::uint32_t vendor_id, - boost::uint32_t device_addr) + boost::uint16_t product_id, + boost::uint16_t vendor_id, + boost::uint16_t device_addr) : _serial(serial), _product_id(product_id), _vendor_id(vendor_id), _device_addr(device_addr) { @@ -66,9 +66,9 @@ public: private: std::string _serial; - boost::uint32_t _product_id; - boost::uint32_t _vendor_id; - boost::uint32_t _device_addr; + boost::uint16_t _product_id; + boost::uint16_t _vendor_id; + boost::uint16_t _device_addr; }; @@ -81,9 +81,9 @@ usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) } std::string serial = libusb::get_serial(dev); - boost::uint32_t product_id = desc.idProduct; - boost::uint32_t vendor_id = desc.idVendor; - boost::uint32_t device_addr = libusb_get_device_address(dev); + boost::uint16_t product_id = desc.idProduct; + boost::uint16_t vendor_id = desc.idVendor; + boost::uint16_t device_addr = libusb_get_device_address(dev); return usb_device_handle::sptr(new libusb1_device_handle_impl( serial, diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index b890a87f9..b3a160462 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -18,7 +18,6 @@ #include "libusb1_base.hpp" #include #include -#include #include #include #include @@ -208,7 +207,7 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len) endpoint, // endpoint buff, // buffer buff_len, // length - callback, // callback + libusb_transfer_cb_fn(callback), // callback this, // user_data 0); // timeout return lut; diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 08f2d2a8e..ad16f6b3a 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -126,7 +126,7 @@ usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, _ad9862_regs.clkout2_div_factor = ad9862_regs_t::CLKOUT2_DIV_FACTOR_2; //write the register settings to the codec - for (uint8_t addr = 0; addr <= 25; addr++) { + for (boost::uint8_t addr = 0; addr <= 25; addr++) { this->send_reg(addr); } @@ -199,7 +199,7 @@ float usrp1_codec_ctrl_impl::get_rx_pga_gain(char which){ **********************************************************************/ static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low) { - return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff; + return float(((boost::uint16_t(high) << 2) | low)*3.3)/0x3ff; } float usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which) diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 451129ef5..936ffd17d 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -287,7 +287,7 @@ public: int usrp_load_eeprom(std::string filestring) { const char *filename = filestring.c_str(); - const uint16_t i2c_addr = 0x50; + const boost::uint16_t i2c_addr = 0x50; //FIXME: verify types int len; @@ -416,7 +416,7 @@ public: } - int usrp_control_write_cmd(uint8_t request, uint16_t value, uint16_t index) + int usrp_control_write_cmd(boost::uint8_t request, boost::uint16_t value, boost::uint16_t index) { return usrp_control_write(request, value, index, 0, 0); } diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp index 4bc18dd16..5fd3987d5 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.cpp +++ b/host/lib/usrp/usrp1/usrp1_iface.cpp @@ -80,7 +80,7 @@ public: boost::uint32_t peek32(boost::uint32_t addr) { - uint32_t value_out; + boost::uint32_t value_out; boost::uint8_t w_index_h = SPI_ENABLE_FPGA & 0xff; boost::uint8_t w_index_l = (SPI_FMT_MSB | SPI_FMT_HDR_1) & 0xff; @@ -100,7 +100,7 @@ public: boost::uint16_t peek16(boost::uint32_t addr) { - uint32_t val = peek32(addr); + boost::uint32_t val = peek32(addr); return boost::uint16_t(val & 0xff); } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index a6806dbc3..627180b11 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -62,7 +62,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) hint.has_key("fw")? hint["fw"] : "usrp1_fw.ihx" ); } - catch(const std::exception &e){ + catch(...){ uhd::print_warning( "Could not locate USRP1 firmware.\n" "Please install the images package.\n" -- cgit v1.2.3 From af1882ab65bb1395f75dd7a7fbdcfc8535c32479 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 23 Sep 2010 18:32:06 -0700 Subject: usrp1: modified control to use the c++ ifstream over fopen --- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 936ffd17d..1dc6e6e25 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -249,38 +249,39 @@ public: unsigned char buf[ep0_size]; int ret; - FILE *fp; - if ((fp = fopen(filename, "rb")) == NULL) { + std::ifstream file; + file.open(filename, std::ios::in | std::ios::binary); + if (not file.good()) { std::cerr << "cannot open fpga input file" << std::endl; - fclose(fp); + file.close(); return -1; } if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_BEGIN) < 0) { std::cerr << "fpga load error" << std::endl; - fclose(fp); + file.close(); return -1; } ssize_t n; - while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { + while ((n = file.readsome((char *)buf, sizeof(buf))) > 0) { ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER, buf, n); if (ret != n) { std::cerr << "fpga load error " << ret << std::endl; - fclose(fp); + file.close(); return -1; } } if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_END) < 0) { std::cerr << "fpga load error" << std::endl; - fclose(fp); + file.close(); return -1; } usrp_set_fpga_hash(hash); - fclose(fp); + file.close(); return 0; } -- cgit v1.2.3 From 42576f1ed98735a69a20cc788d09acd82cb69ae8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 23 Sep 2010 18:46:58 -0700 Subject: usrp1: removed msvc warnings for usrp1 impl code --- host/lib/usrp/usrp1/dsp_impl.cpp | 10 ++++------ host/lib/usrp/usrp1/io_impl.cpp | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 573bce21f..e9a5e60a6 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -107,8 +107,7 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){ return; } case DSP_PROP_HOST_RATE: { - unsigned int rate = - _clock_ctrl->get_master_clock_freq() / val.as(); + size_t rate = size_t(_clock_ctrl->get_master_clock_freq() / val.as()); if ((rate & 0x01) || (rate < 4) || (rate > 256)) { std::cerr << "Decimation must be even and between 4 and 256" @@ -118,7 +117,7 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key_, const wax::obj &val){ _rx_dsp_decim = rate; //TODO Poll every 100ms. Make it selectable? - _rx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() / rate; + _rx_samps_per_poll_interval = size_t(0.1 * _clock_ctrl->get_master_clock_freq() / rate); _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1); } @@ -207,8 +206,7 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){ } case DSP_PROP_HOST_RATE: { - unsigned int rate = - _clock_ctrl->get_master_clock_freq() * 2 / val.as(); + size_t rate = size_t(_clock_ctrl->get_master_clock_freq() * 2 / val.as()); if ((rate & 0x01) || (rate < 8) || (rate > 512)) { std::cerr << "Interpolation rate must be even and between 8 and 512" @@ -219,7 +217,7 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key_, const wax::obj &val){ _tx_dsp_interp = rate; //TODO Poll every 100ms. Make it selectable? - _tx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() * 2 / rate; + _tx_samps_per_poll_interval = size_t(0.1 * _clock_ctrl->get_master_clock_freq() * 2 / rate); _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1); return; diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 146038bd9..73974f2d6 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -184,7 +184,7 @@ bool usrp1_impl::io_impl::get_send_buffs( )); } - return buffs[0].get(); + return buffs[0].get() != NULL; } /*********************************************************************** @@ -277,7 +277,7 @@ static bool get_recv_buffs( ){ UHD_ASSERT_THROW(buffs.size() == 1); buffs[0] = zc_if->get_recv_buff(); - return buffs[0].get(); + return buffs[0].get() != NULL; } size_t usrp1_impl::recv( -- cgit v1.2.3 From f2f4840ff9e15ed21344a5a19d676d548b542e91 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 24 Sep 2010 11:07:14 -0700 Subject: usb: moved msvc stdint file and changed cmake conditional for msvc --- host/lib/transport/CMakeLists.txt | 6 +++--- host/lib/transport/include/stdint.h | 35 ----------------------------------- host/lib/transport/msvc/stdint.h | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 38 deletions(-) delete mode 100644 host/lib/transport/include/stdint.h create mode 100644 host/lib/transport/msvc/stdint.h (limited to 'host/lib') diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 92c9f3181..48b6e9677 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -33,9 +33,9 @@ IF(LIBUSB_FOUND) ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.hpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp ) - IF(WIN32) #include our custom stdint for libusb - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/include) - ENDIF(WIN32) + IF(MSVC) #include our custom stdint for libusb + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/msvc) + ENDIF(MSVC) SET(HAVE_USB_SUPPORT TRUE) ENDIF(LIBUSB_FOUND) diff --git a/host/lib/transport/include/stdint.h b/host/lib/transport/include/stdint.h deleted file mode 100644 index b3eb61aae..000000000 --- a/host/lib/transport/include/stdint.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_LIBUHD_TRANSPORT_STDINT_H -#define INCLUDED_LIBUHD_TRANSPORT_STDINT_H - -#include - -//provide a stdint implementation for libusb - -typedef boost::uint64_t uint64_t; -typedef boost::uint32_t uint32_t; -typedef boost::uint16_t uint16_t; -typedef boost::uint8_t uint8_t; - -typedef boost::int64_t int64_t; -typedef boost::int32_t int32_t; -typedef boost::int16_t int16_t; -typedef boost::int8_t int8_t; - -#endif /* INCLUDED_LIBUHD_TRANSPORT_STDINT_H */ diff --git a/host/lib/transport/msvc/stdint.h b/host/lib/transport/msvc/stdint.h new file mode 100644 index 000000000..b3eb61aae --- /dev/null +++ b/host/lib/transport/msvc/stdint.h @@ -0,0 +1,35 @@ +// +// 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_LIBUHD_TRANSPORT_STDINT_H +#define INCLUDED_LIBUHD_TRANSPORT_STDINT_H + +#include + +//provide a stdint implementation for libusb + +typedef boost::uint64_t uint64_t; +typedef boost::uint32_t uint32_t; +typedef boost::uint16_t uint16_t; +typedef boost::uint8_t uint8_t; + +typedef boost::int64_t int64_t; +typedef boost::int32_t int32_t; +typedef boost::int16_t int16_t; +typedef boost::int8_t int8_t; + +#endif /* INCLUDED_LIBUHD_TRANSPORT_STDINT_H */ -- cgit v1.2.3 From 1dffd5bb5fe16cd35ba54e44e927888e0192e905 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 24 Sep 2010 18:14:32 -0700 Subject: usb: tweaks to usb code to cleanup properly and/or in error conditions --- host/lib/transport/libusb1_base.cpp | 17 +++++++---------- host/lib/transport/libusb1_control.cpp | 1 + host/lib/transport/libusb1_device_handle.cpp | 9 +++++---- 3 files changed, 13 insertions(+), 14 deletions(-) (limited to 'host/lib') diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 1f816c6e2..cd3e4adcf 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -30,9 +30,7 @@ using namespace uhd::transport; **********************************************************/ void libusb::init(libusb_context **ctx, int debug_level) { - if (libusb_init(ctx) < 0) - std::cerr << "error: libusb_init" << std::endl; - + UHD_ASSERT_THROW(libusb_init(ctx) == 0); libusb_set_debug(*ctx, debug_level); } @@ -48,14 +46,13 @@ libusb_device_handle *libusb::open_device(libusb_context *ctx, libusb_device *dev = libusb_dev_list[i]; if (compare_device(dev, handle)) { - libusb_open(dev, &dev_handle); - libusb_unref_device(dev); - break; + if (libusb_open(dev, &dev_handle) == 0) break; } - - libusb_unref_device(dev); } + libusb_free_device_list(libusb_dev_list, true); + if(dev_handle == NULL) + throw std::runtime_error("USB: cannot open device handle"); return dev_handle; } @@ -70,12 +67,12 @@ bool libusb::compare_device(libusb_device *dev, boost::uint16_t device_addr = handle->get_device_addr(); libusb_device_descriptor libusb_desc; - if (libusb_get_device_descriptor(dev, &libusb_desc) < 0) + if (libusb_get_device_descriptor(dev, &libusb_desc) != 0) return false; if (vendor_id != libusb_desc.idVendor) return false; if (product_id != libusb_desc.idProduct) - return false; + return false; if (serial != get_serial(dev)) return false; if (device_addr != libusb_get_device_address(dev)) diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp index 3531128b2..be9b51111 100644 --- a/host/lib/transport/libusb1_control.cpp +++ b/host/lib/transport/libusb1_control.cpp @@ -46,6 +46,7 @@ private: libusb_control_impl::libusb_control_impl(usb_device_handle::sptr handle) { + _ctx = NULL; libusb::init(&_ctx, libusb_debug_level); // Find and open the libusb_device corresponding to the diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp index 7efddd410..6bef37ed2 100644 --- a/host/lib/transport/libusb1_device_handle.cpp +++ b/host/lib/transport/libusb1_device_handle.cpp @@ -77,7 +77,7 @@ usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) libusb_device_descriptor desc; if (libusb_get_device_descriptor(dev, &desc) < 0) { - UHD_ASSERT_THROW("USB: failed to get device descriptor"); + throw std::runtime_error("USB: failed to get device descriptor"); } std::string serial = libusb::get_serial(dev); @@ -104,14 +104,15 @@ std::vector usb_device_handle::get_device_list(boost::u size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list); for (size_t i = 0; i < dev_size; i++) { libusb_device *dev = libusb_device_list[i]; - if(libusb_get_device_descriptor(dev, &desc) < 0) { - UHD_ASSERT_THROW("USB: failed to get device descriptor"); + if(libusb_get_device_descriptor(dev, &desc) != 0) { + continue; //just try the next device, do not throw } if(desc.idVendor == vid && desc.idProduct == pid) { - device_handle_list.push_back(make_usb_device_handle(dev)); + device_handle_list.push_back(make_usb_device_handle(dev)); } } + libusb_free_device_list(libusb_device_list, true); libusb_exit(ctx); return device_handle_list; } -- cgit v1.2.3 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 - host/lib/transport/CMakeLists.txt | 1 - host/lib/transport/libusb1_base.cpp | 289 +++++++++++++++++------ host/lib/transport/libusb1_base.hpp | 162 ++++++++----- host/lib/transport/libusb1_control.cpp | 74 ++---- host/lib/transport/libusb1_device_handle.cpp | 118 --------- host/lib/transport/libusb1_zero_copy.cpp | 83 +++---- 7 files changed, 367 insertions(+), 366 deletions(-) delete mode 100644 host/lib/transport/libusb1_device_handle.cpp (limited to 'host/lib') 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 diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 48b6e9677..61616d077 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -31,7 +31,6 @@ IF(LIBUSB_FOUND) ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_zero_copy.cpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.cpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.hpp - ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp ) IF(MSVC) #include our custom stdint for libusb INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/msvc) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index cd3e4adcf..5ff996642 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -17,107 +17,242 @@ #include "libusb1_base.hpp" #include +#include +#include +#include #include using namespace uhd::transport; -/********************************************************** - * Helper Methods - **********************************************************/ - -/********************************************************** - * libusb namespace - **********************************************************/ -void libusb::init(libusb_context **ctx, int debug_level) -{ - UHD_ASSERT_THROW(libusb_init(ctx) == 0); - libusb_set_debug(*ctx, debug_level); +/*********************************************************************** + * libusb session + **********************************************************************/ +class libusb_session_impl : public libusb::session{ +public: + libusb_session_impl(void){ + UHD_ASSERT_THROW(libusb_init(&_context) == 0); + libusb_set_debug(_context, debug_level); + } + + ~libusb_session_impl(void){ + libusb_exit(_context); + } + + libusb_context *get_context(void) const{ + return _context; + } + +private: + libusb_context *_context; +}; + +libusb::session::sptr libusb::session::get_global_session(void){ + static boost::weak_ptr global_session; + + //not expired -> get existing session + if (not global_session.expired()) return global_session.lock(); + + //create a new global session + sptr new_global_session(new libusb_session_impl()); + global_session = new_global_session; + return new_global_session; } -libusb_device_handle *libusb::open_device(libusb_context *ctx, - usb_device_handle::sptr handle) -{ - libusb_device_handle *dev_handle = NULL; - libusb_device **libusb_dev_list; - size_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list); +/*********************************************************************** + * libusb device + **********************************************************************/ +class libusb_device_impl : public libusb::device{ +public: + libusb_device_impl(libusb_device *dev){ + _session = libusb::session::get_global_session(); + _dev = dev; + } - //find and open the USB device - for (size_t i = 0; i < dev_cnt; i++) { - libusb_device *dev = libusb_dev_list[i]; + ~libusb_device_impl(void){ + libusb_unref_device(this->get()); + } - if (compare_device(dev, handle)) { - if (libusb_open(dev, &dev_handle) == 0) break; - } + libusb_device *get(void) const{ + return _dev; } - libusb_free_device_list(libusb_dev_list, true); - if(dev_handle == NULL) - throw std::runtime_error("USB: cannot open device handle"); - return dev_handle; -} +private: + libusb::session::sptr _session; //always keep a reference to session + libusb_device *_dev; +}; + +/*********************************************************************** + * libusb device list + **********************************************************************/ +class libusb_device_list_impl : public libusb::device_list{ +public: + libusb_device_list_impl(void){ + libusb::session::sptr sess = libusb::session::get_global_session(); -//note: changed order of checks so it only tries to get_serial and get_device_address if vid and pid match -//doing this so it doesn't try to open the device if it's not ours -bool libusb::compare_device(libusb_device *dev, - usb_device_handle::sptr handle) -{ - std::string serial = handle->get_serial(); - boost::uint16_t vendor_id = handle->get_vendor_id(); - boost::uint16_t product_id = handle->get_product_id(); - boost::uint16_t device_addr = handle->get_device_addr(); - - libusb_device_descriptor libusb_desc; - if (libusb_get_device_descriptor(dev, &libusb_desc) != 0) - return false; - if (vendor_id != libusb_desc.idVendor) - return false; - if (product_id != libusb_desc.idProduct) - return false; - if (serial != get_serial(dev)) - return false; - if (device_addr != libusb_get_device_address(dev)) - return false; - - return true; + //allocate a new list of devices + libusb_device** dev_list; + ssize_t ret = libusb_get_device_list(sess->get_context(), &dev_list); + if (ret < 0) throw std::runtime_error("cannot enumerate usb devices"); + + //fill the vector of device references + for (size_t i = 0; i < size_t(ret); i++) _devs.push_back( + libusb::device::sptr(new libusb_device_impl(dev_list[i])) + ); + + //free the device list but dont unref (done in ~device) + libusb_free_device_list(dev_list, false/*dont unref*/); + } + + size_t size(void) const{ + return _devs.size(); + } + + libusb::device::sptr at(size_t i) const{ + return _devs.at(i); + } + +private: + std::vector _devs; +}; + +libusb::device_list::sptr libusb::device_list::make(void){ + return sptr(new libusb_device_list_impl()); } +/*********************************************************************** + * libusb device descriptor + **********************************************************************/ +class libusb_device_descriptor_impl : public libusb::device_descriptor{ +public: + libusb_device_descriptor_impl(libusb::device::sptr dev){ + _dev = dev; + UHD_ASSERT_THROW(libusb_get_device_descriptor(_dev->get(), &_desc) == 0); + } -bool libusb::open_interface(libusb_device_handle *dev_handle, - int interface) -{ - int ret = libusb_claim_interface(dev_handle, interface); - if (ret < 0) { - std::cerr << "error: libusb_claim_interface() " << ret << std::endl; - return false; + const libusb_device_descriptor &get(void) const{ + return _desc; } - else { - return true; + + std::string get_ascii_serial(void) const{ + if (this->get().iSerialNumber == 0) return ""; + + libusb::device_handle::sptr handle( + libusb::device_handle::get_cached_handle(_dev) + ); + + unsigned char buff[512]; + ssize_t ret = libusb_get_string_descriptor_ascii( + handle->get(), this->get().iSerialNumber, buff, sizeof(buff) + ); + if (ret < 0) return ""; //on error, just return empty string + + return std::string((char *)buff, ret); } + +private: + libusb::device::sptr _dev; //always keep a reference to device + libusb_device_descriptor _desc; +}; + +libusb::device_descriptor::sptr libusb::device_descriptor::make(device::sptr dev){ + return sptr(new libusb_device_descriptor_impl(dev)); } +/*********************************************************************** + * libusb device handle + **********************************************************************/ +class libusb_device_handle_impl : public libusb::device_handle{ +public: + libusb_device_handle_impl(libusb::device::sptr dev){ + _dev = dev; + UHD_ASSERT_THROW(libusb_open(_dev->get(), &_handle) == 0); + } + + ~libusb_device_handle_impl(void){ + //release all claimed interfaces + for (size_t i = 0; i < _claimed.size(); i++){ + libusb_release_interface(this->get(), _claimed[i]); + } + libusb_close(_handle); + } + + libusb_device_handle *get(void) const{ + return _handle; + } -std::string libusb::get_serial(libusb_device *dev) -{ - unsigned char buff[32]; + void claim_interface(int interface){ + UHD_ASSERT_THROW(libusb_claim_interface(this->get(), interface) == 0); + _claimed.push_back(interface); + } - libusb_device_descriptor desc; - if (libusb_get_device_descriptor(dev, &desc) < 0) - return ""; +private: + libusb::device::sptr _dev; //always keep a reference to device + libusb_device_handle *_handle; + std::vector _claimed; +}; - if (desc.iSerialNumber == 0) - return ""; +libusb::device_handle::sptr libusb::device_handle::get_cached_handle(device::sptr dev){ + static uhd::dict > handles; - //open the device because we have to - libusb_device_handle *dev_handle; - if (libusb_open(dev, &dev_handle) < 0) - return ""; + //not expired -> get existing session + if (handles.has_key(dev->get()) and not handles[dev->get()].expired()){ + return handles[dev->get()].lock(); + } - if (libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, - buff, sizeof(buff)) < 0) { - return ""; + //create a new global session + sptr new_handle(new libusb_device_handle_impl(dev)); + handles[dev->get()] = new_handle; + return new_handle; +} + +/*********************************************************************** + * libusb special handle + **********************************************************************/ +class libusb_special_handle_impl : public libusb::special_handle{ +public: + libusb_special_handle_impl(libusb::device::sptr dev){ + _dev = dev; } - libusb_close(dev_handle); + libusb::device::sptr get_device(void) const{ + return _dev; + } + + std::string get_serial(void) const{ + return libusb::device_descriptor::make(this->get_device())->get_ascii_serial(); + } + + boost::uint16_t get_vendor_id(void) const{ + return libusb::device_descriptor::make(this->get_device())->get().idVendor; + } + + boost::uint16_t get_product_id(void) const{ + return libusb::device_descriptor::make(this->get_device())->get().idProduct; + } + +private: + libusb::device::sptr _dev; //always keep a reference to device +}; + +libusb::special_handle::sptr libusb::special_handle::make(device::sptr dev){ + return sptr(new libusb_special_handle_impl(dev)); +} + +/*********************************************************************** + * list device handles implementations + **********************************************************************/ +std::vector usb_device_handle::get_device_list( + boost::uint16_t vid, boost::uint16_t pid +){ + std::vector handles; + + libusb::device_list::sptr dev_list = libusb::device_list::make(); + for (size_t i = 0; i < dev_list->size(); i++){ + usb_device_handle::sptr handle = libusb::special_handle::make(dev_list->at(i)); + if (handle->get_vendor_id() == vid and handle->get_product_id() == pid){ + handles.push_back(handle); + } + } - return (char*) buff; + return handles; } diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 484bcf3d9..47d078cde 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -19,74 +19,122 @@ #define INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP #include +#include +#include #include #include namespace uhd { namespace transport { namespace libusb { - /* - * Initialize libusb and set debug level - * Takes a pointer to context pointer because that's - * how libusb rolls. Debug levels. - * - * Level 0: no messages ever printed by the library (default) - * Level 1: error messages are printed to stderr - * Level 2: warning and error messages are printed to stderr - * Level 3: informational messages are printed to stdout, warning - * and error messages are printed to stderr - * - * \param ctx pointer to context pointer - * \param debug_level + + /*! + * This session class holds a global libusb context for this process. + * The get global session call will create a new context if none exists. + * When all references to session are destroyed, the context will be freed. */ - void init(libusb_context **ctx, int debug_level); - - /* - * Open the device specified by a generic handle - * Find the libusb_device cooresponding to the generic handle - * and open it for I/O, which returns a libusb_device_handle - * ready for an interface - * \param ctx the libusb context used for init - * \return a libusb_device_handle ready for action + class session : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + /*! + * Level 0: no messages ever printed by the library (default) + * Level 1: error messages are printed to stderr + * Level 2: warning and error messages are printed to stderr + * Level 3: informational messages are printed to stdout, warning + * and error messages are printed to stderr + */ + static const int debug_level = 0; + + //! get a shared pointer to the global session + static sptr get_global_session(void); + + //! get the underlying libusb context pointer + virtual libusb_context *get_context(void) const = 0; + }; + + /*! + * Holds a device pointer with a reference to the session. */ - libusb_device_handle *open_device(libusb_context *ctx, - usb_device_handle::sptr handle); - - /* - * Compare a libusb device with a generic handle - * Check the descriptors and open the device to check the - * serial number string. Compare values against the given - * handle. The libusb context is already implied in the - * libusb_device. - * \param dev a libusb_device pointer - * \param handle a generic handle specifier - * \return true if handle and device match, false otherwise + class device : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + //! get the underlying device pointer + virtual libusb_device *get(void) const = 0; + }; + + /*! + * This device list class holds a device list that will be + * automatically freed when the last reference is destroyed. */ - bool compare_device(libusb_device *dev, usb_device_handle::sptr handle); - - /* - * Open an interface to the device - * This is a logical operation for operating system housekeeping as - * nothing is sent over the bus. The interface much correspond - * to the USB device descriptors. - * \param dev_handle libusb handle to an opened device - * \param interface integer of the interface to use - * \return true on success, false on error + class device_list : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + //! make a new device list + static sptr make(void); + + //! the number of devices in this list + virtual size_t size() const = 0; + + //! get the device pointer at a particular index + virtual device::sptr at(size_t index) const = 0; + }; + + /*! + * Holds a device descriptor and a reference to the device. */ - bool open_interface(libusb_device_handle *dev_handle, int interface); - - /* - * Get serial number - * The standard USB device descriptor contains an index to an - * actual serial number string descriptor. The index is readily - * readble, but the string descriptor requires probing the device. - * Because this call attempts to open the device, it may not - * succeed because not all USB devices are readily opened. - * The default language is used for the request (English). - * \param dev a libusb_device pointer - * \return string serial number or 0 on error or unavailablity + class device_descriptor : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + //! make a new descriptor from a device reference + static sptr make(device::sptr); + + //! get the underlying device descriptor + virtual const libusb_device_descriptor &get(void) const = 0; + + virtual std::string get_ascii_serial(void) const = 0; + }; + + /*! + * Holds a device handle and a reference to the device. */ - std::string get_serial(libusb_device *dev); + class device_handle : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + //! get a cached handle or make a new one given the device + static sptr get_cached_handle(device::sptr); + + //! get the underlying device handle + virtual libusb_device_handle *get(void) const = 0; + + /*! + * Open USB interfaces for control using magic value + * IN interface: 2 + * OUT interface: 1 + * Control interface: 0 + */ + virtual void claim_interface(int) = 0; + }; + + /*! + * The special handle is our internal implementation of the + * usb device handle which is used publicly to identify a device. + */ + class special_handle : public usb_device_handle { + public: + typedef boost::shared_ptr sptr; + + //! make a new special handle from device + static sptr make(device::sptr); + + //! get the underlying device reference + virtual device::sptr get_device(void) const = 0; + }; + } }} //namespace diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp index be9b51111..c989a788c 100644 --- a/host/lib/transport/libusb1_control.cpp +++ b/host/lib/transport/libusb1_control.cpp @@ -20,7 +20,6 @@ using namespace uhd::transport; -const int libusb_debug_level = 0; const int libusb_timeout = 0; /*********************************************************************** @@ -28,69 +27,38 @@ const int libusb_timeout = 0; **********************************************************************/ class libusb_control_impl : public usb_control { public: - libusb_control_impl(usb_device_handle::sptr handle); - ~libusb_control_impl(); + libusb_control_impl(libusb::device_handle::sptr handle): + _handle(handle) + { + _handle->claim_interface(0 /* control interface */); + } size_t submit(boost::uint8_t request_type, boost::uint8_t request, boost::uint16_t value, boost::uint16_t index, unsigned char *buff, - boost::uint16_t length); + boost::uint16_t length + ){ + return libusb_control_transfer(_handle->get(), + request_type, + request, + value, + index, + buff, + length, + libusb_timeout); + } private: - libusb_context *_ctx; - libusb_device_handle *_dev_handle; + libusb::device_handle::sptr _handle; }; - -libusb_control_impl::libusb_control_impl(usb_device_handle::sptr handle) -{ - _ctx = NULL; - libusb::init(&_ctx, libusb_debug_level); - - // Find and open the libusb_device corresponding to the - // given handle and return the libusb_device_handle - // that can be used for I/O purposes. - _dev_handle = libusb::open_device(_ctx, handle); - - // Open USB interfaces for control using magic value - // IN interface: 2 - // OUT interface: 1 - // Control interface: 0 - libusb::open_interface(_dev_handle, 0); -} - - -libusb_control_impl::~libusb_control_impl() -{ - libusb_close(_dev_handle); - libusb_exit(_ctx); -} - - -size_t libusb_control_impl::submit(boost::uint8_t request_type, - boost::uint8_t request, - boost::uint16_t value, - boost::uint16_t index, - unsigned char *buff, - boost::uint16_t length) -{ - return libusb_control_transfer(_dev_handle, - request_type, - request, - value, - index, - buff, - length, - libusb_timeout); -} - - /*********************************************************************** * USB control public make functions **********************************************************************/ -usb_control::sptr usb_control::make(usb_device_handle::sptr handle) -{ - return sptr(new libusb_control_impl(handle)); +usb_control::sptr usb_control::make(usb_device_handle::sptr handle){ + return sptr(new libusb_control_impl(libusb::device_handle::get_cached_handle( + boost::static_pointer_cast(handle)->get_device() + ))); } diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp deleted file mode 100644 index 6bef37ed2..000000000 --- a/host/lib/transport/libusb1_device_handle.cpp +++ /dev/null @@ -1,118 +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 "libusb1_base.hpp" -#include -#include - -using namespace uhd::transport; - -const int libusb_debug_level = 0; - -/**************************************************************** - * libusb USB device handle implementation class - ***************************************************************/ -class libusb1_device_handle_impl : public usb_device_handle { -public: - libusb1_device_handle_impl(std::string serial, - boost::uint16_t product_id, - boost::uint16_t vendor_id, - boost::uint16_t device_addr) - : _serial(serial), _product_id(product_id), - _vendor_id(vendor_id), _device_addr(device_addr) - { - /* NOP */ - } - - ~libusb1_device_handle_impl() - { - /* NOP */ - } - - std::string get_serial() const - { - return _serial; - } - - boost::uint16_t get_vendor_id() const - { - return _vendor_id; - } - - - boost::uint16_t get_product_id() const - { - return _product_id; - } - - boost::uint16_t get_device_addr() const - { - return _device_addr; - } - -private: - std::string _serial; - boost::uint16_t _product_id; - boost::uint16_t _vendor_id; - boost::uint16_t _device_addr; -}; - - -usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) -{ - libusb_device_descriptor desc; - - if (libusb_get_device_descriptor(dev, &desc) < 0) { - throw std::runtime_error("USB: failed to get device descriptor"); - } - - std::string serial = libusb::get_serial(dev); - boost::uint16_t product_id = desc.idProduct; - boost::uint16_t vendor_id = desc.idVendor; - boost::uint16_t device_addr = libusb_get_device_address(dev); - - return usb_device_handle::sptr(new libusb1_device_handle_impl( - serial, - product_id, - vendor_id, - device_addr)); -} - -std::vector usb_device_handle::get_device_list(boost::uint16_t vid, boost::uint16_t pid) -{ - libusb_context *ctx = NULL; - libusb_device** libusb_device_list; - std::vector device_handle_list; - libusb_device_descriptor desc; - - libusb::init(&ctx, libusb_debug_level); - - size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list); - for (size_t i = 0; i < dev_size; i++) { - libusb_device *dev = libusb_device_list[i]; - if(libusb_get_device_descriptor(dev, &desc) != 0) { - continue; //just try the next device, do not throw - } - if(desc.idVendor == vid && desc.idProduct == pid) { - device_handle_list.push_back(make_usb_device_handle(dev)); - } - } - - libusb_free_device_list(libusb_device_list, true); - libusb_exit(ctx); - return device_handle_list; -} diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index b3a160462..41cd4b3fc 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -24,7 +24,6 @@ using namespace uhd::transport; -const int libusb_debug_level = 0; const int libusb_timeout = 0; /*********************************************************************** @@ -57,8 +56,8 @@ void pp_transfer(libusb_transfer *lut) **********************************************************************/ class usb_endpoint { private: - libusb_device_handle *_dev_handle; - libusb_context *_ctx; + libusb::device_handle::sptr _handle; + libusb::session::sptr _session; int _endpoint; bool _input; @@ -90,9 +89,8 @@ private: void print_transfer_status(libusb_transfer *lut); public: - usb_endpoint(libusb_device_handle *dev_handle, - libusb_context *ctx, int endpoint, bool input, - size_t transfer_size, size_t num_transfers); + usb_endpoint(libusb::device_handle::sptr handle, libusb::session::sptr sess, + int endpoint, bool input, size_t transfer_size, size_t num_transfers); ~usb_endpoint(); @@ -143,11 +141,11 @@ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut) * submit the transfers so that they're ready to return when * data is available. */ -usb_endpoint::usb_endpoint(libusb_device_handle *dev_handle, - libusb_context *ctx, int endpoint, bool input, - size_t transfer_size, size_t num_transfers) - : _dev_handle(dev_handle), - _ctx(ctx), _endpoint(endpoint), _input(input), +usb_endpoint::usb_endpoint( + libusb::device_handle::sptr handle, libusb::session::sptr sess, + int endpoint, bool input, size_t transfer_size, size_t num_transfers) + : _handle(handle), _session(sess), + _endpoint(endpoint), _input(input), _transfer_size(transfer_size), _num_transfers(num_transfers) { unsigned int i; @@ -203,7 +201,7 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len) unsigned int endpoint = ((_endpoint & 0x7f) | (_input ? 0x80 : 0)); libusb_fill_bulk_transfer(lut, // transfer - _dev_handle, // dev_handle + _handle->get(), // dev_handle endpoint, // endpoint buff, // buffer buff_len, // length @@ -356,7 +354,7 @@ bool usb_endpoint::reap_pending_list() { int retval; - if ((retval = libusb_handle_events(_ctx)) < 0) { + if ((retval = libusb_handle_events(_session->get_context())) < 0) { std::cerr << "error: libusb_handle_events: " << retval << std::endl; return false; } @@ -383,7 +381,7 @@ bool usb_endpoint::reap_pending_list_timeout() size_t pending_list_size = _pending_list.size(); - if ((retval = libusb_handle_events_timeout(_ctx, &tv)) < 0) { + if ((retval = libusb_handle_events_timeout(_session->get_context(), &tv)) < 0) { std::cerr << "error: libusb_handle_events: " << retval << std::endl; return false; } @@ -613,11 +611,8 @@ private: usb_endpoint *_rx_ep; usb_endpoint *_tx_ep; - // Maintain libusb values - libusb_context *_rx_ctx; - libusb_context *_tx_ctx; - libusb_device_handle *_rx_dev_handle; - libusb_device_handle *_tx_dev_handle; + libusb::device_handle::sptr _handle; + libusb::session::sptr _session; size_t _recv_buff_size; size_t _send_buff_size; @@ -626,7 +621,7 @@ private: public: typedef boost::shared_ptr sptr; - libusb_zero_copy_impl(usb_device_handle::sptr handle, + libusb_zero_copy_impl(libusb::device_handle::sptr handle, unsigned int rx_endpoint, unsigned int tx_endpoint, size_t recv_buff_size, @@ -646,44 +641,27 @@ public: * Initializes libusb, opens devices, and sets up interfaces for I/O. * Finally, creates endpoints for asynchronous I/O. */ -libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle, +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) - : _rx_ctx(NULL), _tx_ctx(NULL), _rx_dev_handle(NULL), _tx_dev_handle(NULL), + : _handle(handle), _session(libusb::session::get_global_session()), _recv_buff_size(block_size), _send_buff_size(block_size), _num_frames(buff_size / block_size) { - // Initialize libusb with separate contexts to allow - // thread safe operation of transmit and receive - libusb::init(&_rx_ctx, libusb_debug_level); - libusb::init(&_tx_ctx, libusb_debug_level); - - UHD_ASSERT_THROW((_rx_ctx != NULL) && (_tx_ctx != NULL)); - - // Find and open the libusb_device corresponding to the - // given handle and return the libusb_device_handle - // that can be used for I/O purposes. - _rx_dev_handle = libusb::open_device(_rx_ctx, handle); - _tx_dev_handle = libusb::open_device(_tx_ctx, handle); - - // Open USB interfaces for tx/rx using magic values. - // IN interface: 2 - // OUT interface: 1 - // Control interface: 0 - libusb::open_interface(_rx_dev_handle, 2); - libusb::open_interface(_tx_dev_handle, 1); - - _rx_ep = new usb_endpoint(_rx_dev_handle, // libusb device_handle - _rx_ctx, // libusb context + _handle->claim_interface(2 /*in interface*/); + _handle->claim_interface(1 /*out interface*/); + + _rx_ep = new usb_endpoint(_handle, // libusb device_handle + _session, // libusb session w/ context rx_endpoint, // USB endpoint number true, // IN endpoint _recv_buff_size, // buffer size per transfer _num_frames); // number of libusb transfers - _tx_ep = new usb_endpoint(_tx_dev_handle, // libusb device_handle - _tx_ctx, // libusb context + _tx_ep = new usb_endpoint(_handle, // libusb device_handle + _session, // libusb session w/ context tx_endpoint, // USB endpoint number false, // OUT endpoint _send_buff_size, // buffer size per transfer @@ -694,13 +672,7 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle, libusb_zero_copy_impl::~libusb_zero_copy_impl() { delete _rx_ep; - delete _tx_ep; - - libusb_close(_rx_dev_handle); - libusb_close(_tx_dev_handle); - - libusb_exit(_rx_ctx); - libusb_exit(_tx_ctx); + delete _tx_ep; } @@ -755,7 +727,10 @@ usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle, size_t block_size) { - return sptr(new libusb_zero_copy_impl(handle, + 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, -- cgit v1.2.3 From 0816925695aa69a1ae344863fef47d239b3ec8af Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 26 Sep 2010 20:23:23 -0700 Subject: usb: zero copy work, multiple endpoints with single context, async io Heavy work on the zero copy interface and endpoint wrappers to properly use the async io. The global libusb session starts a thread to run the event handler, the async callbacks push completed transfers onto a thread-safe bounded buffer. The managed buffer creation routines use the bounded buffer to efficiently pop off completed transfers. works on linux, throws a weird exception on cleanup --- host/lib/transport/libusb1_base.cpp | 16 ++ host/lib/transport/libusb1_zero_copy.cpp | 474 ++++++++----------------------- 2 files changed, 134 insertions(+), 356 deletions(-) (limited to 'host/lib') diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 5ff996642..26e864459 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include using namespace uhd::transport; @@ -32,9 +33,12 @@ public: libusb_session_impl(void){ UHD_ASSERT_THROW(libusb_init(&_context) == 0); libusb_set_debug(_context, debug_level); + _thread_group.create_thread(boost::bind(&libusb_session_impl::run_event_loop, this)); } ~libusb_session_impl(void){ + _running = false; + _thread_group.join_all(); libusb_exit(_context); } @@ -44,6 +48,18 @@ public: private: libusb_context *_context; + boost::thread_group _thread_group; + bool _running; + + void run_event_loop(void){ + _running = true; + timeval tv; + while(_running){ + tv.tv_sec = 0; + tv.tv_usec = 100000; //100ms + libusb_handle_events_timeout(this->get_context(), &tv); + } + } }; libusb::session::sptr libusb::session::get_global_session(void){ diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 41cd4b3fc..e84793e88 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -17,8 +17,11 @@ #include "libusb1_base.hpp" #include +#include #include -#include +#include +#include +#include #include #include @@ -55,52 +58,57 @@ void pp_transfer(libusb_transfer *lut) * interface provided by the kernel. **********************************************************************/ class usb_endpoint { +public: + typedef boost::shared_ptr sptr; + + usb_endpoint( + libusb::device_handle::sptr handle, + int endpoint, + bool input, + size_t transfer_size, + size_t num_transfers + ); + + ~usb_endpoint(void); + + // Exposed interface for submitting / retrieving transfer buffers + + //! Submit a new transfer that was presumably just filled or emptied. + void submit(libusb_transfer *lut); + + /*! + * 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 + * \return the transfer pointer or NULL if timeout + */ + libusb_transfer *get_lut_with_wait(size_t timeout_ms = 100); + + //Callback use only + void callback_handle_transfer(libusb_transfer *lut); + private: libusb::device_handle::sptr _handle; - libusb::session::sptr _session; int _endpoint; bool _input; size_t _transfer_size; size_t _num_transfers; - // Transfer state lists (transfers are free, pending, or completed) - std::list _free_list; - std::list _pending_list; - std::list _completed_list; + //! hold a bounded buffer of completed transfers + typedef bounded_buffer lut_buff_type; + lut_buff_type::sptr _completed_list; + + //! a list of all transfer structs we allocated + std::vector _all_luts; + + //! a list of shared arrays for the transfer buffers + std::vector > _buffers; // Calls for processing asynchronous I/O libusb_transfer *allocate_transfer(int buff_len); - bool cancel(libusb_transfer *lut); - bool cancel_all(); - bool reap_pending_list(); - bool reap_pending_list_timeout(); - bool reap_completed_list(); - - // Transfer state manipulators - void free_list_add(libusb_transfer *lut); - void pending_list_add(libusb_transfer *lut); - void completed_list_add(libusb_transfer *lut); - libusb_transfer *free_list_get(); - libusb_transfer *completed_list_get(); - bool pending_list_remove(libusb_transfer *lut); - - // Debug use void print_transfer_status(libusb_transfer *lut); - -public: - usb_endpoint(libusb::device_handle::sptr handle, libusb::session::sptr sess, - int endpoint, bool input, size_t transfer_size, size_t num_transfers); - - ~usb_endpoint(); - - // Exposed interface for submitting / retrieving transfer buffers - bool submit(libusb_transfer *lut); - libusb_transfer *get_completed_transfer(); - libusb_transfer *get_free_transfer(); - - //Callback use only - void callback_handle_transfer(libusb_transfer *lut); }; @@ -113,9 +121,8 @@ public: * it from the pending to completed status list. * \param lut pointer to libusb_transfer */ -static void callback(libusb_transfer *lut) -{ - usb_endpoint *endpoint = (usb_endpoint *) lut->user_data; +static void callback(libusb_transfer *lut){ + usb_endpoint *endpoint = (usb_endpoint *) lut->user_data; endpoint->callback_handle_transfer(lut); } @@ -124,14 +131,8 @@ static void callback(libusb_transfer *lut) * Accessor call to allow list access from callback space * \param pointer to libusb_transfer */ -void usb_endpoint::callback_handle_transfer(libusb_transfer *lut) -{ - if (!pending_list_remove(lut)) { - std::cerr << "USB: pending remove failed" << std::endl; - return; - } - - completed_list_add(lut); +void usb_endpoint::callback_handle_transfer(libusb_transfer *lut){ + _completed_list->push_with_wait(lut); } @@ -142,18 +143,27 @@ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut) * data is available. */ usb_endpoint::usb_endpoint( - libusb::device_handle::sptr handle, libusb::session::sptr sess, - int endpoint, bool input, size_t transfer_size, size_t num_transfers) - : _handle(handle), _session(sess), - _endpoint(endpoint), _input(input), - _transfer_size(transfer_size), _num_transfers(num_transfers) + libusb::device_handle::sptr handle, + int endpoint, + bool input, + size_t transfer_size, + size_t num_transfers +): + _handle(handle), + _endpoint(endpoint), + _input(input), + _transfer_size(transfer_size), + _num_transfers(num_transfers) { - unsigned int i; - for (i = 0; i < _num_transfers; i++) { - free_list_add(allocate_transfer(_transfer_size)); + _completed_list = lut_buff_type::make(num_transfers); - if (_input) - submit(free_list_get()); + 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 + if (_input) this->submit(_all_luts.back()); + else _completed_list->push_with_wait(_all_luts.back()); } } @@ -165,22 +175,21 @@ usb_endpoint::usb_endpoint( * the transfers. Libusb will deallocate the data buffer held by * each transfer. */ -usb_endpoint::~usb_endpoint() -{ - cancel_all(); - - while (!_pending_list.empty()) { - if (!reap_pending_list()) - std::cerr << "error: destructor failed to reap" << std::endl; +usb_endpoint::~usb_endpoint(void){ + //cancel all transfers + BOOST_FOREACH(libusb_transfer *lut, _all_luts){ + libusb_cancel_transfer(lut); } - while (!_completed_list.empty()) { - if (!reap_completed_list()) - std::cerr << "error: destructor failed to reap" << std::endl; - } + //collect canceled transfers (drain the queue) + libusb_transfer *lut; + while(_completed_list->pop_with_timed_wait( + lut, boost::posix_time::milliseconds(100) + )); - while (!_free_list.empty()) { - libusb_free_transfer(free_list_get()); + //free all transfers + BOOST_FOREACH(libusb_transfer *lut, _all_luts){ + libusb_free_transfer(lut); } } @@ -192,20 +201,21 @@ usb_endpoint::~usb_endpoint() * \param buff_len size of the individual buffer held by each transfer * \return pointer to an allocated libusb_transfer */ -libusb_transfer *usb_endpoint::allocate_transfer(int buff_len) -{ +libusb_transfer *usb_endpoint::allocate_transfer(int buff_len){ libusb_transfer *lut = libusb_alloc_transfer(0); - unsigned char *buff = new unsigned char[buff_len]; + boost::shared_array buff(new boost::uint8_t[buff_len]); + _buffers.push_back(buff); //store a reference to this shared array unsigned int endpoint = ((_endpoint & 0x7f) | (_input ? 0x80 : 0)); + libusb_transfer_cb_fn lut_callback = libusb_transfer_cb_fn(&callback); libusb_fill_bulk_transfer(lut, // transfer _handle->get(), // dev_handle endpoint, // endpoint - buff, // buffer + buff.get(), // buffer buff_len, // length - libusb_transfer_cb_fn(callback), // callback + lut_callback, // callback this, // user_data 0); // timeout return lut; @@ -218,95 +228,15 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len) * \param lut pointer to libusb_transfer * \return true on success or false on error */ -bool usb_endpoint::submit(libusb_transfer *lut) -{ - int retval; - if ((retval = libusb_submit_transfer(lut)) < 0) { - std::cerr << "error: libusb_submit_transfer: " << retval << std::endl; - return false; - } - - pending_list_add(lut); - return true; -} - - -/* - * Cancel a pending transfer - * Search the pending list for the transfer and cancel if found. - * \param lut pointer to libusb_transfer to cancel - * \return true on success or false if transfer is not found - * - * Note: success only indicates submission of cancelation request. - * Sucessful cancelation is not known until the callback occurs. - */ -bool usb_endpoint::cancel(libusb_transfer *lut) -{ - std::list::iterator iter; - for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) { - if (*iter == lut) { - libusb_cancel_transfer(lut); - return true; - } - } - return false; -} - - -/* - * Cancel all pending transfers - * \return bool true if cancelation request is submitted - * - * Note: success only indicates submission of cancelation request. - * Sucessful cancelation is not known until the callback occurs. - */ -bool usb_endpoint::cancel_all() -{ - std::list::iterator iter; - - for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) { - if (libusb_cancel_transfer(*iter) < 0) { - std::cerr << "error: libusb_cancal_transfer() failed" << std::endl; - return false; - } - } - - return true; -} - - -/* - * Reap completed transfers - * return true if at least one transfer was reaped, false otherwise. - * Check completed transfers for errors and mark as free. This is a - * blocking call. - * \return bool true if a libusb transfer is reaped, false otherwise - */ -bool usb_endpoint::reap_completed_list() -{ - libusb_transfer *lut; - - if (_completed_list.empty()) { - if (!reap_pending_list_timeout()) - return false; - } - - while (!_completed_list.empty()) { - lut = completed_list_get(); - print_transfer_status(lut); - free_list_add(lut); - } - - return true; +void usb_endpoint::submit(libusb_transfer *lut){ + UHD_ASSERT_THROW(libusb_submit_transfer(lut) == 0); } - /* * Print status errors of a completed transfer * \param lut pointer to an libusb_transfer */ -void usb_endpoint::print_transfer_status(libusb_transfer *lut) -{ +void usb_endpoint::print_transfer_status(libusb_transfer *lut){ switch (lut->status) { case LIBUSB_TRANSFER_COMPLETED: if (lut->actual_length < lut->length) { @@ -342,166 +272,14 @@ void usb_endpoint::print_transfer_status(libusb_transfer *lut) } } - -/* - * Reap pending transfers without timeout - * This is a blocking call. Reaping submitted transfers is - * handled by libusb and the assigned callback function. - * Block until at least one transfer is reaped. - * \return true true if a transfer was reaped or false otherwise - */ -bool usb_endpoint::reap_pending_list() -{ - int retval; - - if ((retval = libusb_handle_events(_session->get_context())) < 0) { - std::cerr << "error: libusb_handle_events: " << retval << std::endl; - return false; - } - - return true; -} - - -/* - * Reap pending transfers with timeout - * This call blocks until a transfer is reaped or timeout. - * Reaping submitted transfers is handled by libusb and the - * assigned callback function. Block until at least one - * transfer is reaped or timeout occurs. - * \return true if a transfer was reaped or false otherwise - */ -bool usb_endpoint::reap_pending_list_timeout() -{ - int retval; - timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 100000; //100ms - - size_t pending_list_size = _pending_list.size(); - - if ((retval = libusb_handle_events_timeout(_session->get_context(), &tv)) < 0) { - std::cerr << "error: libusb_handle_events: " << retval << std::endl; - return false; - } - - if (_pending_list.size() < pending_list_size) { - return true; - } - else { - return false; - } -} - - -/* - * Get a free transfer - * The transfer has an empty data bufer for OUT requests - * \return pointer to a libusb_transfer - */ -libusb_transfer *usb_endpoint::get_free_transfer() -{ - if (_free_list.empty()) { - if (!reap_completed_list()) - return NULL; - } - - return free_list_get(); -} - - -/* - * Get a completed transfer - * The transfer has a full data buffer for IN requests - * \return pointer to libusb_transfer - */ -libusb_transfer *usb_endpoint::get_completed_transfer() -{ - if (_completed_list.empty()) { - if (!reap_pending_list_timeout()) - return NULL; - } - - return completed_list_get(); -} - -/* - * List operations - */ -void usb_endpoint::free_list_add(libusb_transfer *lut) -{ - _free_list.push_back(lut); -} - -void usb_endpoint::pending_list_add(libusb_transfer *lut) -{ - _pending_list.push_back(lut); -} - -void usb_endpoint::completed_list_add(libusb_transfer *lut) -{ - _completed_list.push_back(lut); -} - - -/* - * Free and completed lists don't have ordered content - * Pop transfers from the front as needed - */ -libusb_transfer *usb_endpoint::free_list_get() -{ - libusb_transfer *lut; - - if (_free_list.size() == 0) { - return NULL; - } - else { - lut = _free_list.front(); - _free_list.pop_front(); - return lut; - } -} - - -/* - * Free and completed lists don't have ordered content - * Pop transfers from the front as needed - */ -libusb_transfer *usb_endpoint::completed_list_get() -{ +libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){ libusb_transfer *lut; - - if (_completed_list.empty()) { - return NULL; - } - else { - lut = _completed_list.front(); - _completed_list.pop_front(); - return lut; - } + if (_completed_list->pop_with_timed_wait( + lut, boost::posix_time::milliseconds(timeout_ms) + )) return lut; + return NULL; } - -/* - * Search and remove transfer from pending list - * Assuming that the callbacks occur in order, the front element - * should yield the correct transfer. If not, then something else - * is going on. If no transfers match, then something went wrong. - */ -bool usb_endpoint::pending_list_remove(libusb_transfer *lut) -{ - std::list::iterator iter; - for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) { - if (*iter == lut) { - _pending_list.erase(iter); - return true; - } - } - return false; -} - - /*********************************************************************** * Managed buffers **********************************************************************/ @@ -515,17 +293,15 @@ bool usb_endpoint::pending_list_remove(libusb_transfer *lut) class libusb_managed_recv_buffer_impl : public managed_recv_buffer { public: libusb_managed_recv_buffer_impl(libusb_transfer *lut, - usb_endpoint *endpoint) + usb_endpoint::sptr endpoint) : _buff(lut->buffer, lut->length) { _lut = lut; _endpoint = endpoint; } - ~libusb_managed_recv_buffer_impl() - { - if (!_endpoint->submit(_lut)) - std::cerr << "USB: failed to submit IN transfer" << std::endl; + ~libusb_managed_recv_buffer_impl(void){ + _endpoint->submit(_lut); } private: @@ -535,7 +311,7 @@ private: } libusb_transfer *_lut; - usb_endpoint *_endpoint; + usb_endpoint::sptr _endpoint; const boost::asio::const_buffer _buff; }; @@ -551,7 +327,7 @@ private: class libusb_managed_send_buffer_impl : public managed_send_buffer { public: libusb_managed_send_buffer_impl(libusb_transfer *lut, - usb_endpoint *endpoint, + usb_endpoint::sptr endpoint, size_t buff_size) : _buff(lut->buffer, buff_size), _committed(false) { @@ -559,8 +335,7 @@ public: _endpoint = endpoint; } - ~libusb_managed_send_buffer_impl() - { + ~libusb_managed_send_buffer_impl(void){ if (!_committed) { _lut->length = 0; _lut->actual_length = 0; @@ -580,12 +355,14 @@ public: _lut->length = num_bytes; _lut->actual_length = 0; - if (_endpoint->submit(_lut)) { + try{ + _endpoint->submit(_lut); _committed = true; return num_bytes; } - else { - return 0; + catch(const std::exception &e){ + std::cerr << "Error in commit: " << e.what() << std::endl; + return -1; } } @@ -596,7 +373,7 @@ private: } libusb_transfer *_lut; - usb_endpoint *_endpoint; + usb_endpoint::sptr _endpoint; const boost::asio::mutable_buffer _buff; bool _committed; }; @@ -608,11 +385,9 @@ private: class libusb_zero_copy_impl : public usb_zero_copy { private: - usb_endpoint *_rx_ep; - usb_endpoint *_tx_ep; + usb_endpoint::sptr _rx_ep, _tx_ep; libusb::device_handle::sptr _handle; - libusb::session::sptr _session; size_t _recv_buff_size; size_t _send_buff_size; @@ -626,8 +401,6 @@ public: unsigned int tx_endpoint, size_t recv_buff_size, size_t send_buff_size); - - ~libusb_zero_copy_impl(); managed_recv_buffer::sptr get_recv_buff(void); managed_send_buffer::sptr get_send_buff(void); @@ -646,45 +419,38 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle, unsigned int tx_endpoint, size_t buff_size, size_t block_size) - : _handle(handle), _session(libusb::session::get_global_session()), + : _handle(handle), _recv_buff_size(block_size), _send_buff_size(block_size), _num_frames(buff_size / block_size) { _handle->claim_interface(2 /*in interface*/); _handle->claim_interface(1 /*out interface*/); - _rx_ep = new usb_endpoint(_handle, // libusb device_handle - _session, // libusb session w/ context + _rx_ep = usb_endpoint::sptr(new usb_endpoint( + _handle, // libusb device_handle rx_endpoint, // USB endpoint number true, // IN endpoint _recv_buff_size, // buffer size per transfer - _num_frames); // number of libusb transfers + _num_frames // number of libusb transfers + )); - _tx_ep = new usb_endpoint(_handle, // libusb device_handle - _session, // libusb session w/ context + _tx_ep = usb_endpoint::sptr(new usb_endpoint( + _handle, // libusb device_handle tx_endpoint, // USB endpoint number false, // OUT endpoint _send_buff_size, // buffer size per transfer - _num_frames); // number of libusb transfers -} - - -libusb_zero_copy_impl::~libusb_zero_copy_impl() -{ - delete _rx_ep; - delete _tx_ep; + _num_frames // number of libusb transfers + )); } - /* * 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 */ -managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff() -{ - libusb_transfer *lut = _rx_ep->get_completed_transfer(); +managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){ + libusb_transfer *lut = _rx_ep->get_lut_with_wait(/* TODO timeout API */); if (lut == NULL) { return managed_recv_buffer::sptr(); } @@ -702,9 +468,8 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff() * (timeout or error). * \return pointer to a managed send buffer */ -managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff() -{ - libusb_transfer *lut = _tx_ep->get_free_transfer(); +managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){ + libusb_transfer *lut = _tx_ep->get_lut_with_wait(/* TODO timeout API */); if (lut == NULL) { return managed_send_buffer::sptr(); } @@ -736,6 +501,3 @@ usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle, buff_size, block_size)); } - - - -- cgit v1.2.3 From 86213f8de2cc4ca671f9afbcf475c744fe7aebcb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 26 Sep 2010 20:54:58 -0700 Subject: usb: disable thread interruption on wait calls --- host/lib/transport/libusb1_zero_copy.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'host/lib') diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index e84793e88..d3888240b 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -132,6 +133,7 @@ static void callback(libusb_transfer *lut){ * \param pointer to libusb_transfer */ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut){ + boost::this_thread::disable_interruption di; //disable because the wait can throw _completed_list->push_with_wait(lut); } @@ -182,10 +184,7 @@ usb_endpoint::~usb_endpoint(void){ } //collect canceled transfers (drain the queue) - libusb_transfer *lut; - while(_completed_list->pop_with_timed_wait( - lut, boost::posix_time::milliseconds(100) - )); + while (this->get_lut_with_wait() != NULL); //free all transfers BOOST_FOREACH(libusb_transfer *lut, _all_luts){ @@ -273,6 +272,7 @@ void usb_endpoint::print_transfer_status(libusb_transfer *lut){ } libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){ + 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) -- cgit v1.2.3 From 017e7202468a8800335c05afd4a85cb52c6171e6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 26 Sep 2010 21:07:43 -0700 Subject: usrp1: add print out messages when loading images --- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 1dc6e6e25..76e8ce368 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -38,6 +38,8 @@ enum firmware_code { #define FX2_FIRMWARE_LOAD 0xa0 +static const bool load_img_msg = true; + /*********************************************************************** * Helper Functions **********************************************************************/ @@ -178,6 +180,7 @@ public: unsigned char reset_n = 0; //hit the reset line + if (load_img_msg) std::cout << "Loading firmware image " << filestring << "..." << std::flush; usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1); @@ -213,7 +216,7 @@ public: //wait for things to settle boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); - + if (load_img_msg) std::cout << " done" << std::endl; return USRP_FIRMWARE_LOAD_SUCCESS; } //type anything else is unhandled @@ -249,6 +252,7 @@ public: unsigned char buf[ep0_size]; int ret; + if (load_img_msg) std::cout << "Loading FPGA image: " << filestring << "..." << std::flush; std::ifstream file; file.open(filename, std::ios::in | std::ios::binary); if (not file.good()) { @@ -282,6 +286,7 @@ public: usrp_set_fpga_hash(hash); file.close(); + if (load_img_msg) std::cout << " done" << std::endl; return 0; } -- cgit v1.2.3 From 1180615fe2ee1e976aeb9139eb1378fb93befb0f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 26 Sep 2010 22:45:56 -0700 Subject: usb: added some documentation to wrapper base --- host/lib/transport/libusb1_base.hpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'host/lib') diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 47d078cde..64a1442d1 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -24,6 +24,13 @@ #include #include +/*********************************************************************** + * Libusb object oriented smart pointer wrappers: + * The following wrappers provide allocation and automatic deallocation + * for various libusb data types and handles. The construction routines + * also store tables of already allocated structures to avoid multiple + * occurrences of opened handles (for example). + **********************************************************************/ namespace uhd { namespace transport { namespace libusb { -- cgit v1.2.3 From 694404694515e293da6b8949e74af5f469a2e1e5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 27 Sep 2010 00:32:46 -0700 Subject: usb: use the proper libusb include (in path set by pkgconfig) --- host/lib/transport/libusb1_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 64a1442d1..04c1d6574 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include /*********************************************************************** * Libusb object oriented smart pointer wrappers: -- cgit v1.2.3 From 2f62c39b7135728ed06faa06db46004323b1c70f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 27 Sep 2010 11:35:28 -0700 Subject: uhd: fix warning by adding brackets for while(cond){}; --- host/examples/test_async_messages.cpp | 2 +- host/lib/transport/libusb1_zero_copy.cpp | 2 +- host/lib/usrp/usrp2/io_impl.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'host/lib') diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp index 4c9d18121..0a5c076ea 100644 --- a/host/examples/test_async_messages.cpp +++ b/host/examples/test_async_messages.cpp @@ -58,7 +58,7 @@ void test_no_async_message(uhd::usrp::single_usrp::sptr sdev){ " Got unexpected event code 0x%x.\n" ) % async_md.event_code << std::endl; //clear the async messages - while (dev->recv_async_msg(async_md, 0)); + while (dev->recv_async_msg(async_md, 0)){}; } else{ std::cout << boost::format( diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index d3888240b..b089d11e0 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -184,7 +184,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() != NULL){}; //free all transfers BOOST_FOREACH(libusb_transfer *lut, _all_luts){ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 91a1b2344..65411801d 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -150,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().get()); + while (data_transport->get_recv_buff().get()){}; } //the number of recv frames is the number for the first transport -- cgit v1.2.3 From fd15965442d5a8805a4730022f8d500841f8448d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 27 Sep 2010 16:04:04 -0700 Subject: usrp1: filter the discovery routine on the serial --- host/lib/usrp/usrp1/usrp1_impl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 627180b11..80ea49e9d 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -96,7 +96,10 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) device_addr_t new_addr; new_addr["type"] = "usrp1"; new_addr["serial"] = handle->get_serial(); - usrp1_addrs.push_back(new_addr); + //this is a found usrp1 when a hint serial is not specified or it matches + if (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]){ + usrp1_addrs.push_back(new_addr); + } } return usrp1_addrs; -- cgit v1.2.3 From 852f5c5f7b31bfb2e7561a86ca9f5380bd53d130 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 10:21:11 -0700 Subject: dboard: better warnings for invalid IDs and invalid ID combinations --- host/lib/usrp/dboard_manager.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index ab80875f5..181f843a0 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -18,6 +18,7 @@ #include "dboard_ctor_args.hpp" #include #include +#include #include #include #include @@ -176,10 +177,6 @@ static args_t get_dboard_args( ){ //special case, the none id was provided, use the following ids if (dboard_id == dboard_id_t::none() or force_to_unknown){ - std::cerr << boost::format( - "Warning: unknown dboard-id or dboard-id combination: %s\n" - " -> defaulting to the unknown board type" - ) % dboard_id.to_pp_string() << std::endl; UHD_ASSERT_THROW(get_id_to_args_map().has_key(0xfff1)); UHD_ASSERT_THROW(get_id_to_args_map().has_key(0xfff0)); switch(unit){ @@ -191,6 +188,9 @@ 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( + "Unknown dboard ID: %s.\n" + ) % dboard_id.to_pp_string())); return get_dboard_args(unit, dboard_id, true); } @@ -214,12 +214,25 @@ dboard_manager_impl::dboard_manager_impl( (get_xcvr_id_to_id_map()[tx_dboard_id] == rx_dboard_id) ); + //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( + "Unknown transceiver board ID combination...\n" + "RX dboard ID: %s\n" + "TX dboard ID: %s\n" + ) % rx_dboard_id.to_pp_string() % tx_dboard_id.to_pp_string())); + } + //extract dboard constructor and settings (force to unknown for messed up xcvr status) dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; - boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(dboard_iface::UNIT_RX, rx_dboard_id, rx_dboard_is_xcvr != this_dboard_is_xcvr); + boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args( + dboard_iface::UNIT_RX, rx_dboard_id, rx_dboard_is_xcvr != this_dboard_is_xcvr + ); dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs; - boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(dboard_iface::UNIT_TX, tx_dboard_id, tx_dboard_is_xcvr != this_dboard_is_xcvr); + boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args( + dboard_iface::UNIT_TX, tx_dboard_id, tx_dboard_is_xcvr != this_dboard_is_xcvr + ); //initialize the gpio pins before creating subdevs set_nice_dboard_if(); -- cgit v1.2.3 From 137aa0ab1ed0b8f7f31a6c484fcf5a845682db80 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 10:24:53 -0700 Subject: usrp1: modify fpga file load to use read (readsome seems to not work here in windows land) --- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 76e8ce368..2e1bd85cd 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -267,8 +267,9 @@ public: return -1; } - ssize_t n; - while ((n = file.readsome((char *)buf, sizeof(buf))) > 0) { + while (not file.eof()) { + file.read((char *)buf, sizeof(buf)); + size_t n = file.gcount(); ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER, buf, n); if (ret != n) { -- cgit v1.2.3 From f5bdb7ccb39ef23d4b2c0872fe410e9d5d031958 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 11:08:41 -0700 Subject: usrp1: move the get handles call into the for loop scope to facilitate decontruction --- host/lib/usrp/usrp1/usrp1_impl.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 627180b11..a56649305 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -74,14 +74,14 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) boost::uint16_t vid = hint.has_key("uninit") ? FX2_VENDOR_ID : USRP1_VENDOR_ID; boost::uint16_t pid = hint.has_key("uninit") ? FX2_PRODUCT_ID : USRP1_PRODUCT_ID; - //see what we got on the USB bus - std::vector device_list = - usb_device_handle::get_device_list(vid, pid); - - if(device_list.size() == 0) return usrp1_addrs; //return nothing if no USRPs found + // Important note: + // The get device list calls are nested inside the for loop. + // This allows the usb guts to decontruct when not in use, + // so that re-enumeration after fw load can occur successfully. + // This requirement is a courtesy of libusb1.0 on windows. //find the usrps and load firmware - BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) { usb_control::sptr ctrl_transport = usb_control::make(handle); usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_firmware(usrp1_fw_image); @@ -90,9 +90,8 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) //get descriptors again with serial number, but using the initialized VID/PID now since we have firmware vid = USRP1_VENDOR_ID; pid = USRP1_PRODUCT_ID; - device_list = usb_device_handle::get_device_list(vid, pid); - BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) { device_addr_t new_addr; new_addr["type"] = "usrp1"; new_addr["serial"] = handle->get_serial(); -- cgit v1.2.3 From b70d4430d4a898fe99b54740a1c4821ed9a1077b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 15:31:38 -0700 Subject: wbx: fix for id swap typo --- host/lib/usrp/dboard/db_wbx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index ccd897674..e473ce41e 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -154,7 +154,7 @@ static dboard_base::sptr make_wbx(dboard_base::ctor_args_t args){ } UHD_STATIC_BLOCK(reg_wbx_dboards){ - dboard_manager::register_dboard(0x0052, 0x0053, &make_wbx, "WBX"); + dboard_manager::register_dboard(0x0053, 0x0052, &make_wbx, "WBX"); } /*********************************************************************** -- 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/lib') 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 302078474312ad87db69a9c06b63e3f8a0c19cd5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 29 Sep 2010 09:51:41 -0700 Subject: usrp1: fixed compile time warning, tweaked fw load message --- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 5d73e6dd9..5043aed7d 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -180,7 +180,7 @@ public: unsigned char reset_n = 0; //hit the reset line - if (load_img_msg) std::cout << "Loading firmware image " << filestring << "..." << std::flush; + if (load_img_msg) std::cout << "Loading firmware image: " << filestring << "..." << std::flush; usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1); @@ -272,7 +272,7 @@ public: size_t n = file.gcount(); ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER, buf, n); - if (ret != n) { + if (ret < 0 or size_t(ret) != n) { std::cerr << "fpga load error " << ret << std::endl; file.close(); return -1; -- 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/lib') 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 04c74a3c74907e55e339f1568a1d5b4cdf190daf Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 10:07:13 -0700 Subject: usrp1: replace byteswap with htonx (it was wrong to just swap) also removed unused poke and peek 16 bit calls --- host/lib/usrp/usrp1/usrp1_iface.cpp | 16 ++-------------- host/lib/usrp/usrp1/usrp1_iface.hpp | 14 -------------- 2 files changed, 2 insertions(+), 28 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp index 5fd3987d5..64ced2905 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.cpp +++ b/host/lib/usrp/usrp1/usrp1_iface.cpp @@ -49,7 +49,7 @@ public: ******************************************************************/ void poke32(boost::uint32_t addr, boost::uint32_t value) { - boost::uint32_t swapped = byteswap(value); + boost::uint32_t swapped = uhd::htonx(value); if (iface_debug) { std::cout.fill('0'); @@ -72,12 +72,6 @@ public: std::cerr << "USRP: failed memory write: " << ret << std::endl; } - void poke16(boost::uint32_t, boost::uint16_t) - { - //fpga only handles 32 bit writes - std::cerr << "USRP: unsupported operation: poke16()" << std::endl; - } - boost::uint32_t peek32(boost::uint32_t addr) { boost::uint32_t value_out; @@ -95,13 +89,7 @@ public: if (ret < 0) std::cerr << "USRP: failed memory read: " << ret << std::endl; - return byteswap(value_out); - } - - boost::uint16_t peek16(boost::uint32_t addr) - { - boost::uint32_t val = peek32(addr); - return boost::uint16_t(val & 0xff); + return uhd::ntohx(value_out); } /******************************************************************* diff --git a/host/lib/usrp/usrp1/usrp1_iface.hpp b/host/lib/usrp/usrp1/usrp1_iface.hpp index 9a3fdd6bc..3f608584a 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.hpp +++ b/host/lib/usrp/usrp1/usrp1_iface.hpp @@ -53,20 +53,6 @@ public: */ virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; - /*! - * Write a register (16 bits) - * \param addr the address - * \param data the 16bit data - */ - virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; - - /*! - * read a register (16 bits) - * \param addr the address - * \return the 16bit data - */ - virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; - /*! * Perform an spi transaction. * \param which_slave the slave device number -- cgit v1.2.3 From e4fffed05dda57bb37d693a3a26ea6a903c925f7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 11:32:21 -0700 Subject: usb: set rt thread priority for the libusb event loop --- host/lib/transport/libusb1_base.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'host/lib') diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 26e864459..49f524a32 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -16,6 +16,7 @@ // #include "libusb1_base.hpp" +#include #include #include #include @@ -23,6 +24,7 @@ #include #include +using namespace uhd; using namespace uhd::transport; /*********************************************************************** @@ -52,6 +54,7 @@ private: bool _running; void run_event_loop(void){ + set_thread_priority_safe(); _running = true; timeval tv; while(_running){ -- cgit v1.2.3