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/lib/usrp/usrp1/dsp_impl.cpp | 10 ++++++++-- host/lib/usrp/usrp1/mboard_impl.cpp | 39 +++++++++++++++++++------------------ host/lib/usrp/usrp1/usrp1_impl.hpp | 6 ++++++ 3 files changed, 34 insertions(+), 21 deletions(-) (limited to 'host/lib/usrp/usrp1') 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/usrp/usrp1') 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 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/usrp/usrp1') 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/usrp/usrp1') 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/usrp/usrp1') 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/usrp/usrp1') 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