diff options
Diffstat (limited to 'host/lib/usrp')
26 files changed, 614 insertions, 421 deletions
| diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index bbc9716b1..89e707718 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -15,8 +15,6 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -static const bool rfx_debug = false; -  // IO Pin functions  #define POWER_IO     (1 << 7)   // Low enables power supply  #define ANTSW_IO     (1 << 6)   // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2 @@ -56,10 +54,23 @@ using namespace uhd::usrp;  using namespace boost::assign;  /*********************************************************************** - * The RFX series of dboards + * The RFX Series constants   **********************************************************************/ -static const float _max_rx_pga0_gain = 45; +static const bool rfx_debug = false; + +static const prop_names_t rfx_tx_antennas = list_of("TX/RX"); + +static const prop_names_t rfx_rx_antennas = list_of("TX/RX")("RX2"); +static const uhd::dict<std::string, gain_range_t> rfx_tx_gain_ranges; //empty + +static const uhd::dict<std::string, gain_range_t> rfx_rx_gain_ranges = map_list_of +    ("PGA0", gain_range_t(0, 45, float(0.022))) +; + +/*********************************************************************** + * The RFX series of dboards + **********************************************************************/  class rfx_xcvr : public xcvr_dboard_base{  public:      rfx_xcvr( @@ -85,6 +96,10 @@ private:      void set_rx_lo_freq(double freq);      void set_tx_lo_freq(double freq);      void set_rx_ant(const std::string &ant); +    void set_tx_ant(const std::string &ant); +    void set_rx_gain(float gain, const std::string &name); +    void set_tx_gain(float gain, const std::string &name); +      void set_rx_pga0_gain(float gain);      /*! @@ -161,8 +176,10 @@ rfx_xcvr::rfx_xcvr(      this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);      this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); -    //set the gpio directions +    //set the gpio directions and atr controls (identically)      boost::uint16_t output_enables = POWER_IO | ANTSW_IO | MIXER_IO; +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, output_enables); +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, output_enables);      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, output_enables);      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, output_enables); @@ -189,19 +206,11 @@ rfx_xcvr::~rfx_xcvr(void){  }  /*********************************************************************** - * Helper Methods + * Antenna Handling   **********************************************************************/ -void rfx_xcvr::set_rx_lo_freq(double freq){ -    _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq); -} - -void rfx_xcvr::set_tx_lo_freq(double freq){ -    _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq); -} -  void rfx_xcvr::set_rx_ant(const std::string &ant){      //validate input -    UHD_ASSERT_THROW(ant == "TX/RX" or ant == "RX2"); +    assert_has(rfx_rx_antennas, ant, "rfx rx antenna name");      //set the rx atr regs that change with antenna setting      this->get_iface()->set_atr_reg( @@ -213,22 +222,51 @@ void rfx_xcvr::set_rx_ant(const std::string &ant){      _rx_ant = ant;  } -void rfx_xcvr::set_rx_pga0_gain(float gain){ -    //clip the input -    gain = std::clip<float>(gain, 0, _max_rx_pga0_gain); +void rfx_xcvr::set_tx_ant(const std::string &ant){ +    assert_has(rfx_tx_antennas, ant, "rfx tx antenna name"); +    //only one antenna option, do nothing +} + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +void rfx_xcvr::set_tx_gain(float, const std::string &name){ +    assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name"); +    UHD_ASSERT_THROW(false); //no gains to set +} + +void rfx_xcvr::set_rx_gain(float gain, const std::string &name){ +    assert_has(rfx_rx_gain_ranges.keys(), name, "rfx rx gain name"); +    if(name == "PGA0"){ +        this->set_rx_pga0_gain(gain); +    } +    else UHD_ASSERT_THROW(false); +} -    //voltage level constants +void rfx_xcvr::set_rx_pga0_gain(float gain){ +    //voltage level constants (negative slope)      static const float max_volts = float(.2), min_volts = float(1.2); -    static const float slope = (max_volts-min_volts)/_max_rx_pga0_gain; +    static const float slope = (max_volts-min_volts)/45;      //calculate the voltage for the aux dac -    float dac_volts = gain*slope + min_volts; +    float dac_volts = std::clip<float>(gain*slope + min_volts, max_volts, min_volts);      //write the new voltage to the aux dac      this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, 1, dac_volts); -    //shadow the setting (does not account for precision loss) -    _rx_pga0_gain = gain; +    //shadow the actual gain setting +    _rx_pga0_gain = (dac_volts - min_volts)/slope; +} + +/*********************************************************************** + * Tuning + **********************************************************************/ +void rfx_xcvr::set_rx_lo_freq(double freq){ +    _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq); +} + +void rfx_xcvr::set_tx_lo_freq(double freq){ +    _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq);  }  double rfx_xcvr::set_lo_freq( @@ -258,8 +296,8 @@ double rfx_xcvr::set_lo_freq(          (8, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_8)      ; -    double actual_freq, ref_freq = this->get_iface()->get_clock_rate(unit); -    int R, BS, P, B, A; +    double actual_freq=0, ref_freq = this->get_iface()->get_clock_rate(unit); +    int R=0, BS=0, P=0, B=0, A=0;      /*       * The goal here to to loop though possible R dividers, @@ -364,12 +402,12 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_GAIN_RANGE: -        UHD_ASSERT_THROW(name == "PGA0"); -        val = gain_range_t(0, _max_rx_pga0_gain, float(0.022)); +        assert_has(rfx_rx_gain_ranges.keys(), name, "rfx rx gain name"); +        val = rfx_rx_gain_ranges[name];          return;      case SUBDEV_PROP_GAIN_NAMES: -        val = prop_names_t(1, "PGA0"); +        val = prop_names_t(rfx_rx_gain_ranges.keys());          return;      case SUBDEV_PROP_FREQ: @@ -384,10 +422,8 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          val = _rx_ant;          return; -    case SUBDEV_PROP_ANTENNA_NAMES:{ -            prop_names_t ants = list_of("TX/RX")("RX2"); -            val = ants; -        } +    case SUBDEV_PROP_ANTENNA_NAMES: +        val = rfx_rx_antennas;          return;      case SUBDEV_PROP_QUADRATURE: @@ -422,16 +458,15 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){      switch(key.as<subdev_prop_t>()){      case SUBDEV_PROP_FREQ: -        set_rx_lo_freq(val.as<double>()); +        this->set_rx_lo_freq(val.as<double>());          return;      case SUBDEV_PROP_GAIN: -        UHD_ASSERT_THROW(name == "PGA0"); -        set_rx_pga0_gain(val.as<float>()); +        this->set_rx_gain(val.as<float>(), name);          return;      case SUBDEV_PROP_ANTENNA: -        set_rx_ant(val.as<std::string>()); +        this->set_rx_ant(val.as<std::string>());          return;      default: UHD_THROW_PROP_SET_ERROR(); @@ -456,15 +491,13 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        val = float(0); -        return; -      case SUBDEV_PROP_GAIN_RANGE: -        val = gain_range_t(0, 0, 0); +        assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name"); +        //no controllable tx gains, will not get here          return;      case SUBDEV_PROP_GAIN_NAMES: -        val = prop_names_t(); //empty +        val = prop_names_t(rfx_tx_gain_ranges.keys());          return;      case SUBDEV_PROP_FREQ: @@ -480,7 +513,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_ANTENNA_NAMES: -        val = prop_names_t(1, "TX/RX"); +        val = rfx_tx_antennas;          return;      case SUBDEV_PROP_QUADRATURE: @@ -515,16 +548,15 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){      switch(key.as<subdev_prop_t>()){      case SUBDEV_PROP_FREQ: -        set_tx_lo_freq(val.as<double>()); +        this->set_tx_lo_freq(val.as<double>());          return;      case SUBDEV_PROP_GAIN: -        //no gains to set! +        this->set_tx_gain(val.as<float>(), name);          return;      case SUBDEV_PROP_ANTENNA: -        //its always set to tx/rx, so we only allow this value -        UHD_ASSERT_THROW(val.as<std::string>() == "TX/RX"); +        this->set_tx_ant(val.as<std::string>());          return;      default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 2a8a3a9f2..23654860f 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -164,7 +164,9 @@ wbx_xcvr::wbx_xcvr(      this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);      this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); -    //set the gpio directions +    //set the gpio directions and atr controls (identically) +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK);      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK);      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK);      if (wbx_debug) std::cerr << boost::format( @@ -303,7 +305,7 @@ double wbx_xcvr::set_lo_freq(      double actual_freq, pfd_freq;      double ref_freq = this->get_iface()->get_clock_rate(unit); -    int R, BS, N, FRAC, MOD; +    int R=0, BS=0, N=0, FRAC=0, MOD=0;      int RFdiv = 1;      adf4350_regs_t::reference_divide_by_2_t T     = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;      adf4350_regs_t::reference_doubler_t     D     = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED;     diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 3472229f4..d4d5f184e 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -169,7 +169,9 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){      //enable only the clocks we need      this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); -    //set the gpio directions +    //set the gpio directions and atr controls (identically) +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); +    this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK);      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK);      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK); diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 8161727e5..01352039e 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -298,7 +298,8 @@ void dboard_manager_impl::set_nice_dboard_if(void){      //set nice settings on each unit      BOOST_FOREACH(dboard_iface::unit_t unit, units){          _iface->set_gpio_ddr(unit, 0x0000); //all inputs -        _iface->set_atr_reg(unit, dboard_iface::ATR_REG_IDLE, 0x0000); //all low +        _iface->write_gpio(unit, 0x0000); //all low +        _iface->set_pin_ctrl(unit, 0x0000); //all gpio          _iface->set_clock_enabled(unit, false); //clock off      }  } diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index a8c104485..f4aa82669 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -121,6 +121,10 @@ public:          return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq);      } +    tune_result_t set_rx_freq(double target_freq, double lo_off){ +        return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq, lo_off); +    } +      freq_range_t get_rx_freq_range(void){          return _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>();      } @@ -168,6 +172,10 @@ public:          return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq);      } +    tune_result_t set_tx_freq(double target_freq, double lo_off){ +        return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq, lo_off); +    } +      freq_range_t get_tx_freq_range(void){          return _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>();      } diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index f9907e21e..99d0b8bdd 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -18,12 +18,20 @@  #This file will be included by cmake, use absolute paths!  LIBUHD_APPEND_SOURCES( -    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_control.cpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.cpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.hpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.cpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.hpp      ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_impl.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_iface.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dsp_impl.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.cpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.hpp      ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.cpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.hpp      ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.cpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.hpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_regs.hpp  ) diff --git a/host/lib/usrp/usrp2/clock_control.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 72f1f1c7a..4c5207203 100644 --- a/host/lib/usrp/usrp2/clock_control.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -15,21 +15,19 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#include "usrp2_impl.hpp" -#include "clock_control.hpp" +#include "clock_ctrl.hpp"  #include "ad9510_regs.hpp"  #include "usrp2_regs.hpp" //spi slave constants  #include <boost/cstdint.hpp>  using namespace uhd; -using namespace uhd::usrp;  /*!   * A usrp2 clock control specific to the ad9510 ic.   */ -class clock_control_ad9510 : public clock_control{ +class clock_ctrl_impl : public clock_ctrl{  public: -    clock_control_ad9510(usrp2_iface::sptr iface){ +    clock_ctrl_impl(usrp2_iface::sptr iface){          _iface = iface;          _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; @@ -70,7 +68,7 @@ public:      } -    ~clock_control_ad9510(void){ +    ~clock_ctrl_impl(void){          /* private clock enables, must be set here */          this->enable_dac_clock(false);          this->enable_adc_clock(false); @@ -81,7 +79,9 @@ public:          _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1;          _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS;          _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; +        _ad9510_regs.bypass_divider_out7 = 1;          this->write_reg(0x43); +        this->write_reg(0x57);          this->update_regs();      } @@ -90,7 +90,9 @@ public:          _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1;          _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS;          _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; +        _ad9510_regs.bypass_divider_out6 = 1;          this->write_reg(0x42); +        this->write_reg(0x55);          this->update_regs();      } @@ -132,7 +134,9 @@ private:              ad9510_regs_t::POWER_DOWN_LVPECL_OUT3_NORMAL :              ad9510_regs_t::POWER_DOWN_LVPECL_OUT3_SAFE_PD;          _ad9510_regs.output_level_lvpecl_out3 = ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT3_810MV; +        _ad9510_regs.bypass_divider_out3 = 1;          this->write_reg(0x3F); +        this->write_reg(0x4F);          this->update_regs();      } @@ -141,7 +145,9 @@ private:          _ad9510_regs.power_down_lvds_cmos_out4 = enb? 0 : 1;          _ad9510_regs.lvds_cmos_select_out4 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT4_LVDS;          _ad9510_regs.output_level_lvds_out4 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT4_1_75MA; +        _ad9510_regs.bypass_divider_out4 = 1;          this->write_reg(0x40); +        this->write_reg(0x51);          this->update_regs();      } @@ -152,6 +158,6 @@ private:  /***********************************************************************   * Public make function for the ad9510 clock control   **********************************************************************/ -clock_control::sptr clock_control::make_ad9510(usrp2_iface::sptr iface){ -    return clock_control::sptr(new clock_control_ad9510(iface)); +clock_ctrl::sptr clock_ctrl::make(usrp2_iface::sptr iface){ +    return sptr(new clock_ctrl_impl(iface));  } diff --git a/host/lib/usrp/usrp2/clock_control.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp index b64a53196..706bf4246 100644 --- a/host/lib/usrp/usrp2/clock_control.hpp +++ b/host/lib/usrp/usrp2/clock_ctrl.hpp @@ -15,23 +15,23 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#ifndef INCLUDED_CLOCK_CONTROL_HPP -#define INCLUDED_CLOCK_CONTROL_HPP +#ifndef INCLUDED_CLOCK_CTRL_HPP +#define INCLUDED_CLOCK_CTRL_HPP  #include "usrp2_iface.hpp"  #include <boost/shared_ptr.hpp>  #include <boost/utility.hpp> -class clock_control : boost::noncopyable{ +class clock_ctrl : boost::noncopyable{  public: -    typedef boost::shared_ptr<clock_control> sptr; +    typedef boost::shared_ptr<clock_ctrl> sptr;      /*!       * Make a clock config for the ad9510 ic.       * \param _iface a pointer to the usrp2 interface object       * \return a new clock control object       */ -    static sptr make_ad9510(usrp2_iface::sptr iface); +    static sptr make(usrp2_iface::sptr iface);      /*!       * Enable/disable the rx dboard clock. @@ -57,4 +57,4 @@ public:  }; -#endif /* INCLUDED_CLOCK_CONTROL_HPP */ +#endif /* INCLUDED_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp new file mode 100644 index 000000000..d698216ba --- /dev/null +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -0,0 +1,91 @@ +// +// 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 <http://www.gnu.org/licenses/>. +// + +#include "codec_ctrl.hpp" +#include "ad9777_regs.hpp" +#include "usrp2_regs.hpp" +#include <boost/cstdint.hpp> +#include <boost/foreach.hpp> +#include <iostream> + +static const bool codec_ctrl_debug = false; + +using namespace uhd; + +/*! + * A usrp2 codec control specific to the ad9777 ic. + */ +class codec_ctrl_impl : public codec_ctrl{ +public: +    codec_ctrl_impl(usrp2_iface::sptr iface){ +        _iface = iface; + +        //setup the ad9777 dac +        _ad9777_regs.x_1r_2r_mode = ad9777_regs_t::X_1R_2R_MODE_1R; +        _ad9777_regs.filter_interp_rate = ad9777_regs_t::FILTER_INTERP_RATE_4X; +        _ad9777_regs.mix_mode = ad9777_regs_t::MIX_MODE_REAL; +        _ad9777_regs.pll_divide_ratio = ad9777_regs_t::PLL_DIVIDE_RATIO_DIV1; +        _ad9777_regs.pll_state = ad9777_regs_t::PLL_STATE_ON; +        _ad9777_regs.auto_cp_control = ad9777_regs_t::AUTO_CP_CONTROL_AUTO; +        //I dac values +        _ad9777_regs.idac_fine_gain_adjust = 0; +        _ad9777_regs.idac_coarse_gain_adjust = 0xf; +        _ad9777_regs.idac_offset_adjust_lsb = 0; +        _ad9777_regs.idac_offset_adjust_msb = 0; +        //Q dac values +        _ad9777_regs.qdac_fine_gain_adjust = 0; +        _ad9777_regs.qdac_coarse_gain_adjust = 0xf; +        _ad9777_regs.qdac_offset_adjust_lsb = 0; +        _ad9777_regs.qdac_offset_adjust_msb = 0; +        //write all regs +        for(boost::uint8_t addr = 0; addr <= 0xC; addr++){ +            this->send_ad9777_reg(addr); +        } + +        //power-up adc +        _iface->poke32(FR_MISC_CTRL_ADC, FRF_MISC_CTRL_ADC_ON); +    } + +    ~codec_ctrl_impl(void){ +        //power-down dac +        _ad9777_regs.power_down_mode = 1; +        this->send_ad9777_reg(0); + +        //power-down adc +        _iface->poke32(FR_MISC_CTRL_ADC, FRF_MISC_CTRL_ADC_OFF); +    } + +private: +    ad9777_regs_t _ad9777_regs; +    usrp2_iface::sptr _iface; + +    void send_ad9777_reg(boost::uint8_t addr){ +        boost::uint16_t reg = _ad9777_regs.get_write_reg(addr); +        if (codec_ctrl_debug) std::cout << "send_ad9777_reg: " << std::hex << reg << std::endl; +        _iface->transact_spi( +            SPI_SS_AD9777, spi_config_t::EDGE_RISE, +            reg, 16, false /*no rb*/ +        ); +    } +}; + +/*********************************************************************** + * Public make function for the usrp2 codec control + **********************************************************************/ +codec_ctrl::sptr codec_ctrl::make(usrp2_iface::sptr iface){ +    return sptr(new codec_ctrl_impl(iface)); +} diff --git a/host/lib/usrp/usrp2/codec_ctrl.hpp b/host/lib/usrp/usrp2/codec_ctrl.hpp new file mode 100644 index 000000000..0ee52f476 --- /dev/null +++ b/host/lib/usrp/usrp2/codec_ctrl.hpp @@ -0,0 +1,38 @@ +// +// 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 <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_CODEC_CTRL_HPP +#define INCLUDED_CODEC_CTRL_HPP + +#include "usrp2_iface.hpp" +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> + +class codec_ctrl : boost::noncopyable{ +public: +    typedef boost::shared_ptr<codec_ctrl> sptr; + +    /*! +     * Make a codec control for the DAC and ADC. +     * \param _iface a pointer to the usrp2 interface object +     * \return a new codec control object +     */ +    static sptr make(usrp2_iface::sptr iface); + +}; + +#endif /* INCLUDED_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index 372a5af07..0a2e4b550 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -16,7 +16,7 @@  //  #include "usrp2_iface.hpp" -#include "clock_control.hpp" +#include "clock_ctrl.hpp"  #include "usrp2_regs.hpp" //wishbone address constants  #include <uhd/usrp/dboard_iface.hpp>  #include <uhd/types/dict.hpp> @@ -33,14 +33,16 @@ using namespace boost::assign;  class usrp2_dboard_iface : public dboard_iface{  public: -    usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl); +    usrp2_dboard_iface(usrp2_iface::sptr iface, clock_ctrl::sptr clock_ctrl);      ~usrp2_dboard_iface(void);      void write_aux_dac(unit_t, int, float);      float read_aux_adc(unit_t, int); +    void set_pin_ctrl(unit_t, boost::uint16_t);      void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);      void set_gpio_ddr(unit_t, boost::uint16_t); +    void write_gpio(unit_t, boost::uint16_t);      boost::uint16_t read_gpio(unit_t);      void write_i2c(boost::uint8_t, const byte_vector_t &); @@ -66,8 +68,9 @@ public:  private:      usrp2_iface::sptr _iface; -    clock_control::sptr _clk_ctrl; +    clock_ctrl::sptr _clock_ctrl;      boost::uint32_t _ddr_shadow; +    boost::uint32_t _gpio_shadow;      uhd::dict<unit_t, ad5624_regs_t> _dac_regs;      void _write_aux_dac(unit_t); @@ -78,26 +81,19 @@ private:   **********************************************************************/  dboard_iface::sptr make_usrp2_dboard_iface(      usrp2_iface::sptr iface, -    clock_control::sptr clk_ctrl +    clock_ctrl::sptr clock_ctrl  ){ -    return dboard_iface::sptr(new usrp2_dboard_iface(iface, clk_ctrl)); +    return dboard_iface::sptr(new usrp2_dboard_iface(iface, clock_ctrl));  }  /***********************************************************************   * Structors   **********************************************************************/ -usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl){ +usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_ctrl::sptr clock_ctrl){      _iface = iface; -    _clk_ctrl = clk_ctrl; +    _clock_ctrl = clock_ctrl;      _ddr_shadow = 0; - -    //set the selection mux to use atr -    boost::uint32_t new_sels = 0x0; -    for(size_t i = 0; i < 16; i++){ -        new_sels |= FRF_GPIO_SEL_ATR << (i*2); -    } -    _iface->poke32(FR_GPIO_TX_SEL, new_sels); -    _iface->poke32(FR_GPIO_RX_SEL, new_sels); +    _gpio_shadow = 0;      //reset the aux dacs      _dac_regs[UNIT_RX] = ad5624_regs_t(); @@ -123,8 +119,8 @@ double usrp2_dboard_iface::get_clock_rate(unit_t){  void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){      switch(unit){ -    case UNIT_RX: _clk_ctrl->enable_rx_dboard_clock(enb); return; -    case UNIT_TX: _clk_ctrl->enable_tx_dboard_clock(enb); return; +    case UNIT_RX: _clock_ctrl->enable_rx_dboard_clock(enb); return; +    case UNIT_TX: _clock_ctrl->enable_tx_dboard_clock(enb); return;      }  } @@ -136,6 +132,21 @@ static const uhd::dict<dboard_iface::unit_t, int> unit_to_shift = map_list_of      (dboard_iface::UNIT_TX, 16)  ; +void usrp2_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){ +    //calculate the new selection mux setting +    boost::uint32_t new_sels = 0x0; +    for(size_t i = 0; i < 16; i++){ +        bool is_bit_set = bool(value & (0x1 << i)); +        new_sels |= ((is_bit_set)? FRF_GPIO_SEL_ATR : FRF_GPIO_SEL_GPIO) << (i*2); +    } + +    //write the selection mux value to register +    switch(unit){ +    case UNIT_RX: _iface->poke32(FR_GPIO_RX_SEL, new_sels); return; +    case UNIT_TX: _iface->poke32(FR_GPIO_TX_SEL, new_sels); return; +    } +} +  void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){      _ddr_shadow = \          (_ddr_shadow & ~(0xffff << unit_to_shift[unit])) | @@ -143,6 +154,13 @@ void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){      _iface->poke32(FR_GPIO_DDR, _ddr_shadow);  } +void usrp2_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value){ +    _gpio_shadow = \ +        (_gpio_shadow & ~(0xffff << unit_to_shift[unit])) | +        (boost::uint32_t(value) << unit_to_shift[unit]); +    _iface->poke32(FR_GPIO_IO, _gpio_shadow); +} +  boost::uint16_t usrp2_dboard_iface::read_gpio(unit_t unit){      return boost::uint16_t(_iface->peek32(FR_GPIO_IO) >> unit_to_shift[unit]);  } diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 403faf5cf..0ac39d2a3 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -38,9 +38,7 @@ void usrp2_impl::dboard_init(void){      _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes()));      //create a new dboard interface and manager -    dboard_iface::sptr _dboard_iface( -        make_usrp2_dboard_iface(_iface, _clk_ctrl) -    ); +    _dboard_iface = make_usrp2_dboard_iface(_iface, _clock_ctrl);      _dboard_manager = dboard_manager::make(          _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface      ); @@ -123,6 +121,10 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){          val = _rx_db_eeprom.id;          return; +    case DBOARD_PROP_DBOARD_IFACE: +        val = _dboard_iface; +        return; +      default: UHD_THROW_PROP_GET_ERROR();      }  } @@ -172,6 +174,10 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){          val = _tx_db_eeprom.id;          return; +    case DBOARD_PROP_DBOARD_IFACE: +        val = _dboard_iface; +        return; +      default: UHD_THROW_PROP_GET_ERROR();      }  } diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index fc4c5479e..195a9bc53 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -94,9 +94,6 @@ void usrp2_impl::init_ddc_config(void){      _ddc_decim = default_decim;      _ddc_freq = 0;      update_ddc_config(); - -    //initial command that kills streaming (in case if was left on) -    issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);  }  void usrp2_impl::update_ddc_config(void){ diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index e80001ff2..75f5b1779 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -34,7 +34,7 @@ extern "C" {  //defines the protocol version in this shared header  //increment this value when the protocol is changed -#define USRP2_PROTO_VERSION 2 +#define USRP2_PROTO_VERSION 3  //used to differentiate control packets over data port  #define USRP2_INVALID_VRT_HEADER 0 @@ -53,13 +53,8 @@ typedef enum{      //USRP2_CTRL_ID_FOR_SURE, //TODO error condition enums      //USRP2_CTRL_ID_SUX_MAN, -    USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO = 'a', -    USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE = 'A', -    USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO = 'b', - -    USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO = 'm', -    USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE = 'M', -    USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO = 'n', +    USRP2_CTRL_ID_WAZZUP_BRO = 'a', +    USRP2_CTRL_ID_WAZZUP_DUDE = 'A',      USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO = 's',      USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE = 'S', @@ -70,9 +65,6 @@ typedef enum{      USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO = 'h',      USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE = 'H', -    USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO = '{', -    USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE = '}', -      USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO = 'p',      USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE = 'P', @@ -99,7 +91,6 @@ typedef struct{      _SINS_ uint32_t seq;      union{          _SINS_ uint32_t ip_addr; -        _SINS_ uint8_t mac_addr[6];          struct {              _SINS_ uint8_t dev;              _SINS_ uint8_t miso_edge; @@ -114,15 +105,6 @@ typedef struct{              _SINS_ uint8_t data[sizeof(_SINS_ uint32_t)];          } i2c_args;          struct { -            _SINS_ uint8_t now; //stream now? -            _SINS_ uint8_t continuous; //auto-reload commmands? -            _SINS_ uint8_t chain; -            _SINS_ uint8_t _pad[1]; -            _SINS_ uint32_t secs; -            _SINS_ uint32_t ticks; -            _SINS_ uint32_t num_samps; -        } stream_cmd; -        struct {              _SINS_ uint32_t addr;              _SINS_ uint32_t data;              _SINS_ uint8_t num_bytes; //1, 2, 4 diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 2634e84aa..79b18fb63 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -16,6 +16,7 @@  //  #include "usrp2_impl.hpp" +#include "usrp2_regs.hpp"  #include <uhd/transport/convert_types.hpp>  #include <boost/format.hpp>  #include <boost/asio.hpp> //htonl and ntohl @@ -30,71 +31,35 @@ namespace asio = boost::asio;   * Helper Functions   **********************************************************************/  void usrp2_impl::io_init(void){ -    //setup otw type -    _otw_type.width = 16; -    _otw_type.shift = 0; -    _otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; +    //setup rx otw type +    _rx_otw_type.width = 16; +    _rx_otw_type.shift = 0; +    _rx_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; -    //initially empty copy buffer -    _rx_copy_buff = asio::buffer("", 0); - -    //init the expected rx seq number -    _rx_stream_id_to_packet_seq[0] = 0; +    //setup tx otw type +    _tx_otw_type.width = 16; +    _tx_otw_type.shift = 0; +    _tx_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;      //send a small data packet so the usrp2 knows the udp source port -    //and the maximum number of lines (32 bit words) per packet      managed_send_buffer::sptr send_buff = _data_transport->get_send_buff(); -    boost::uint32_t data[2] = { -        htonl(USRP2_INVALID_VRT_HEADER), -        htonl(_max_rx_samples_per_packet) -    }; -    memcpy(send_buff->cast<void*>(), data, sizeof(data)); -    send_buff->done(sizeof(data)); -} - -/*********************************************************************** - * Receive Raw Data - **********************************************************************/ -void usrp2_impl::recv_raw(rx_metadata_t &metadata){ -    //do a receive -    _rx_smart_buff = _data_transport->get_recv_buff(); - -    //unpack the vrt header -    size_t num_packet_words32 = _rx_smart_buff->size()/sizeof(boost::uint32_t); -    if (num_packet_words32 == 0){ -        _rx_copy_buff = boost::asio::buffer("", 0); -        return; //must exit here after setting the buffer -    } -    const boost::uint32_t *vrt_hdr = _rx_smart_buff->cast<const boost::uint32_t *>(); -    size_t num_header_words32_out, num_payload_words32_out, packet_count_out; -    try{ -        vrt::unpack( -            metadata,                //output -            vrt_hdr,                 //input -            num_header_words32_out,  //output -            num_payload_words32_out, //output -            num_packet_words32,      //input -            packet_count_out,        //output -            get_master_clock_freq() -        ); -    }catch(const std::exception &e){ -        std::cerr << "bad vrt header: " << e.what() << std::endl; -        _rx_copy_buff = boost::asio::buffer("", 0); -        return; //must exit here after setting the buffer -    } - -    //handle the packet count / sequence number -    size_t expected_packet_count = _rx_stream_id_to_packet_seq[metadata.stream_id]; -    if (packet_count_out != expected_packet_count){ -        std::cerr << "S" << (packet_count_out - expected_packet_count)%16; -    } -    _rx_stream_id_to_packet_seq[metadata.stream_id] = (packet_count_out+1)%16; - -    //setup the rx buffer to point to the data -    _rx_copy_buff = asio::buffer( -        vrt_hdr + num_header_words32_out, -        num_payload_words32_out*sizeof(boost::uint32_t) +    boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); +    memcpy(send_buff->cast<void*>(), &data, sizeof(data)); +    send_buff->commit(sizeof(data)); + +    //setup RX DSP regs +    std::cout << "RX samples per packet: " << get_max_recv_samps_per_packet() << std::endl; +    _iface->poke32(FR_RX_CTRL_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); +    _iface->poke32(FR_RX_CTRL_NCHANNELS, 1); +    _iface->poke32(FR_RX_CTRL_CLEAR_OVERRUN, 1); //reset +    _iface->poke32(FR_RX_CTRL_VRT_HEADER, 0 +        | (0x1 << 28) //if data with stream id +        | (0x1 << 26) //has trailer +        | (0x3 << 22) //integer time other +        | (0x1 << 20) //fractional time sample count      ); +    _iface->poke32(FR_RX_CTRL_VRT_STREAM_ID, 0); +    _iface->poke32(FR_RX_CTRL_VRT_TRAILER, 0);  }  /*********************************************************************** @@ -102,49 +67,18 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){   **********************************************************************/  size_t usrp2_impl::send(      const asio::const_buffer &buff, -    const tx_metadata_t &metadata_, -    const io_type_t &io_type +    const tx_metadata_t &metadata, +    const io_type_t &io_type, +    send_mode_t send_mode  ){ -    tx_metadata_t metadata = metadata_; //rw copy to change later - -    transport::managed_send_buffer::sptr send_buff = _data_transport->get_send_buff(); -    boost::uint32_t *tx_mem = send_buff->cast<boost::uint32_t *>(); -    size_t num_samps = std::min(std::min( -        asio::buffer_size(buff)/io_type.size, -        size_t(_max_tx_samples_per_packet)), -        send_buff->size()/io_type.size -    ); - -    //kill the end of burst flag if this is a fragment -    if (asio::buffer_size(buff)/io_type.size < num_samps) -        metadata.end_of_burst = false; - -    size_t num_header_words32, num_packet_words32; -    size_t packet_count = _tx_stream_id_to_packet_seq[metadata.stream_id]++; - -    //pack metadata into a vrt header -    vrt::pack( -        metadata,            //input -        tx_mem,              //output -        num_header_words32,  //output -        num_samps,           //input -        num_packet_words32,  //output -        packet_count,        //input -        get_master_clock_freq() -    ); - -    boost::uint32_t *items = tx_mem + num_header_words32; //offset for data - -    //copy-convert the samples into the send buffer -    convert_io_type_to_otw_type( -        asio::buffer_cast<const void*>(buff), io_type, -        (void*)items, _otw_type, -        num_samps +    return vrt_packet_handler::send( +        _packet_handler_send_state, //last state of the send handler +        buff, metadata, send_mode,  //buffer to empty and samples metadata +        io_type, _tx_otw_type,      //input and output types to convert +        get_master_clock_freq(),    //master clock tick rate +        _data_transport,            //zero copy interface +        get_max_send_samps_per_packet()      ); - -    //send and return number of samples -    send_buff->done(num_packet_words32*sizeof(boost::uint32_t)); -    return num_samps;  }  /*********************************************************************** @@ -153,44 +87,14 @@ size_t usrp2_impl::send(  size_t usrp2_impl::recv(      const asio::mutable_buffer &buff,      rx_metadata_t &metadata, -    const io_type_t &io_type +    const io_type_t &io_type, +    recv_mode_t recv_mode  ){ -    //perform a receive if no rx data is waiting to be copied -    if (asio::buffer_size(_rx_copy_buff) == 0){ -        _fragment_offset_in_samps = 0; -        recv_raw(metadata); -    } -    //otherwise flag the metadata to show that is is a fragment -    else{ -        metadata = rx_metadata_t(); -    } - -    //extract the number of samples available to copy -    //and a pointer into the usrp2 received items memory -    size_t bytes_to_copy = asio::buffer_size(_rx_copy_buff); -    if (bytes_to_copy == 0) return 0; //nothing to receive -    size_t num_samps = std::min( -        asio::buffer_size(buff)/io_type.size, -        bytes_to_copy/sizeof(boost::uint32_t) +    return vrt_packet_handler::recv( +        _packet_handler_recv_state, //last state of the recv handler +        buff, metadata, recv_mode,  //buffer to fill and samples metadata +        io_type, _rx_otw_type,      //input and output types to convert +        get_master_clock_freq(),    //master clock tick rate +        _data_transport             //zero copy interface      ); -    const boost::uint32_t *items = asio::buffer_cast<const boost::uint32_t*>(_rx_copy_buff); - -    //setup the fragment flags and offset -    metadata.more_fragments = asio::buffer_size(buff)/io_type.size < num_samps; -    metadata.fragment_offset = _fragment_offset_in_samps; -    _fragment_offset_in_samps += num_samps; //set for next time - -    //copy-convert the samples from the recv buffer -    convert_otw_type_to_io_type( -        (const void*)items, _otw_type, -        asio::buffer_cast<void*>(buff), io_type, -        num_samps -    ); - -    //update the rx copy buffer to reflect the bytes copied -    _rx_copy_buff = asio::buffer( -        items + num_samps, bytes_to_copy - num_samps*sizeof(boost::uint32_t) -    ); - -    return num_samps;  } diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 36bef4f25..a2aeadf16 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -17,13 +17,13 @@  #include "usrp2_impl.hpp"  #include "usrp2_regs.hpp" -#include "ad9777_regs.hpp"  #include <uhd/usrp/mboard_props.hpp>  #include <uhd/utils/assert.hpp> +#include <uhd/utils/algorithm.hpp>  #include <uhd/types/mac_addr.hpp>  #include <uhd/types/dict.hpp>  #include <boost/bind.hpp> -#include <boost/asio.hpp> //htonl and ntohl +#include <boost/asio/ip/address_v4.hpp>  #include <boost/assign/list_of.hpp>  using namespace uhd; @@ -37,32 +37,6 @@ void usrp2_impl::mboard_init(void){          boost::bind(&usrp2_impl::mboard_get, this, _1, _2),          boost::bind(&usrp2_impl::mboard_set, this, _1, _2)      ); - -    _clk_ctrl = clock_control::make_ad9510(_iface); - -    //setup the ad9777 dac -    ad9777_regs_t ad9777_regs; -    ad9777_regs.x_1r_2r_mode = ad9777_regs_t::X_1R_2R_MODE_1R; -    ad9777_regs.filter_interp_rate = ad9777_regs_t::FILTER_INTERP_RATE_4X; -    ad9777_regs.mix_mode = ad9777_regs_t::MIX_MODE_REAL; -    ad9777_regs.pll_divide_ratio = ad9777_regs_t::PLL_DIVIDE_RATIO_DIV1; -    ad9777_regs.pll_state = ad9777_regs_t::PLL_STATE_OFF; -    ad9777_regs.auto_cp_control = ad9777_regs_t::AUTO_CP_CONTROL_ENB; -    //I dac values -    ad9777_regs.idac_fine_gain_adjust = 0; -    ad9777_regs.idac_coarse_gain_adjust = 0xf; -    ad9777_regs.idac_offset_adjust_lsb = 0; -    ad9777_regs.idac_offset_adjust_msb = 0; -    //Q dac values -    ad9777_regs.qdac_fine_gain_adjust = 0; -    ad9777_regs.qdac_coarse_gain_adjust = 0xf; -    ad9777_regs.qdac_offset_adjust_lsb = 0; -    ad9777_regs.qdac_offset_adjust_msb = 0; -    //write all regs -    for(boost::uint8_t addr = 0; addr <= 0xC; addr++){ -        boost::uint16_t data = ad9777_regs.get_write_reg(addr); -        _iface->transact_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, data, 16, false /*no rb*/); -    }  }  void usrp2_impl::init_clock_config(void){ @@ -97,62 +71,55 @@ void usrp2_impl::update_clock_config(void){      //clock source ref 10mhz      switch(_clock_config.ref_source){ -    case clock_config_t::REF_INT : _iface->poke32(FR_CLOCK_CONTROL, 0x10); break; -    case clock_config_t::REF_SMA : _iface->poke32(FR_CLOCK_CONTROL, 0x1C); break; -    case clock_config_t::REF_MIMO: _iface->poke32(FR_CLOCK_CONTROL, 0x15); break; +    case clock_config_t::REF_INT : _iface->poke32(FR_MISC_CTRL_CLOCK, 0x10); break; +    case clock_config_t::REF_SMA : _iface->poke32(FR_MISC_CTRL_CLOCK, 0x1C); break; +    case clock_config_t::REF_MIMO: _iface->poke32(FR_MISC_CTRL_CLOCK, 0x15); break;      default: throw std::runtime_error("usrp2: unhandled clock configuration reference source");      }      //clock source ref 10mhz      bool use_external = _clock_config.ref_source != clock_config_t::REF_INT; -    _clk_ctrl->enable_external_ref(use_external); +    _clock_ctrl->enable_external_ref(use_external);  }  void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){ -    //set ticks and seconds -    _iface->poke32(FR_TIME64_SECS, time_spec.secs); +    //set the ticks      _iface->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq())); -    //set the register to latch it all in +    //set the flags register      boost::uint32_t imm_flags = (now)? FRF_TIME64_LATCH_NOW : FRF_TIME64_LATCH_NEXT_PPS;      _iface->poke32(FR_TIME64_IMM, imm_flags); + +    //set the seconds (latches in all 3 registers) +    _iface->poke32(FR_TIME64_SECS, time_spec.secs);  }  void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ -    //setup the out data -    usrp2_ctrl_data_t out_data; -    out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO); -    out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0; -    out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs); -    out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.get_ticks(get_master_clock_freq())); - -    //set these to defaults, then change in the switch statement -    out_data.data.stream_cmd.continuous = 0; -    out_data.data.stream_cmd.chain = 0; -    out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps); - -    //setup chain, num samps, and continuous below -    switch(stream_cmd.stream_mode){ -    case stream_cmd_t::STREAM_MODE_START_CONTINUOUS: -        out_data.data.stream_cmd.continuous = 1; -        break; - -    case stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS: -        out_data.data.stream_cmd.num_samps = htonl(0); -        break; - -    case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE: -        //all set by defaults above -        break; - -    case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE: -        out_data.data.stream_cmd.chain = 1; -        break; -    } - -    //send and recv -    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); -    UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE); +    UHD_ASSERT_THROW(stream_cmd.num_samps <= FR_RX_CTRL_MAX_SAMPS_PER_CMD); + +    //setup the mode to instruction flags +    typedef boost::tuple<bool, bool, bool> inst_t; +    static const uhd::dict<stream_cmd_t::stream_mode_t, inst_t> mode_to_inst = boost::assign::map_list_of +                                                            //reload, chain, samps +        (stream_cmd_t::STREAM_MODE_START_CONTINUOUS,   inst_t(true,  true,  false)) +        (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS,    inst_t(false, false, false)) +        (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true)) +        (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true,  true)) +    ; + +    //setup the instruction flag values +    bool inst_reload, inst_chain, inst_samps; +    boost::tie(inst_reload, inst_chain, inst_samps) = mode_to_inst[stream_cmd.stream_mode]; + +    //issue the stream command +    _iface->poke32(FR_RX_CTRL_STREAM_CMD, FR_RX_CTRL_MAKE_CMD( +        (inst_samps)? stream_cmd.num_samps : ((inst_chain)? get_max_recv_samps_per_packet() : 1), +        (stream_cmd.stream_now)? 1 : 0, +        (inst_chain)? 1 : 0, +        (inst_reload)? 1 : 0 +    )); +    _iface->poke32(FR_RX_CTRL_TIME_SECS,  stream_cmd.time_spec.secs); +    _iface->poke32(FR_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_ticks(get_master_clock_freq()));  }  /*********************************************************************** @@ -165,30 +132,15 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){      //handle the other props      if (key.type() == typeid(std::string)){          if (key.as<std::string>() == "mac-addr"){ -            //setup the out data -            usrp2_ctrl_data_t out_data; -            out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO); - -            //send and recv -            usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); -            UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); - -            //extract the address -            val = mac_addr_t::from_bytes(in_data.data.mac_addr).to_string(); +            byte_vector_t bytes = _iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_MAC_ADDR, 6); +            val = mac_addr_t::from_bytes(bytes).to_string();              return;          }          if (key.as<std::string>() == "ip-addr"){ -            //setup the out data -            usrp2_ctrl_data_t out_data; -            out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); - -            //send and recv -            usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); -            UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); - -            //extract the address -            val = boost::asio::ip::address_v4(ntohl(in_data.data.ip_addr)).to_string(); +            boost::asio::ip::address_v4::bytes_type bytes; +            std::copy(_iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_IP_ADDR, 4), bytes); +            val = boost::asio::ip::address_v4(bytes).to_string();              return;          }      } @@ -259,27 +211,15 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){      //handle the other props      if (key.type() == typeid(std::string)){          if (key.as<std::string>() == "mac-addr"){ -            //setup the out data -            usrp2_ctrl_data_t out_data; -            out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO); -            mac_addr_t mac_addr = mac_addr_t::from_string(val.as<std::string>()); -            std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr); - -            //send and recv -            usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); -            UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); +            byte_vector_t bytes = mac_addr_t::from_string(val.as<std::string>()).to_bytes(); +            _iface->write_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_MAC_ADDR, bytes);              return;          }          if (key.as<std::string>() == "ip-addr"){ -            //setup the out data -            usrp2_ctrl_data_t out_data; -            out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO); -            out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(val.as<std::string>()).to_ulong()); - -            //send and recv -            usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); -            UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); +            byte_vector_t bytes(4); +            std::copy(boost::asio::ip::address_v4::from_string(val.as<std::string>()).to_bytes(), bytes); +            _iface->write_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_IP_ADDR, bytes);              return;          }      } diff --git a/host/lib/usrp/usrp2/serdes_ctrl.cpp b/host/lib/usrp/usrp2/serdes_ctrl.cpp new file mode 100644 index 000000000..dde22b499 --- /dev/null +++ b/host/lib/usrp/usrp2/serdes_ctrl.cpp @@ -0,0 +1,46 @@ +// +// 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 <http://www.gnu.org/licenses/>. +// + +#include "serdes_ctrl.hpp" +#include "usrp2_regs.hpp" + +using namespace uhd; + +/*! + * A usrp2 serdes control implementation + */ +class serdes_ctrl_impl : public serdes_ctrl{ +public: +    serdes_ctrl_impl(usrp2_iface::sptr iface){ +        _iface = iface; +        _iface->poke32(FR_MISC_CTRL_SERDES, FRF_MISC_CTRL_SERDES_ENABLE | FRF_MISC_CTRL_SERDES_RXEN); +    } + +    ~serdes_ctrl_impl(void){ +        _iface->poke32(FR_MISC_CTRL_SERDES, 0); //power-down +    } + +private: +    usrp2_iface::sptr _iface; +}; + +/*********************************************************************** + * Public make function for the usrp2 serdes control + **********************************************************************/ +serdes_ctrl::sptr serdes_ctrl::make(usrp2_iface::sptr iface){ +    return sptr(new serdes_ctrl_impl(iface)); +} diff --git a/host/lib/usrp/usrp2/serdes_ctrl.hpp b/host/lib/usrp/usrp2/serdes_ctrl.hpp new file mode 100644 index 000000000..586238739 --- /dev/null +++ b/host/lib/usrp/usrp2/serdes_ctrl.hpp @@ -0,0 +1,40 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_SERDES_CTRL_HPP +#define INCLUDED_SERDES_CTRL_HPP + +#include "usrp2_iface.hpp" +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> + +class serdes_ctrl : boost::noncopyable{ +public: +    typedef boost::shared_ptr<serdes_ctrl> sptr; + +    /*! +     * Make a serdes control object for the usrp2 serdes port. +     * \param _iface a pointer to the usrp2 interface object +     * \return a new serdes control object +     */ +    static sptr make(usrp2_iface::sptr iface); + +    //TODO fill me in with virtual methods + +}; + +#endif /* INCLUDED_SERDES_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 7158c58d0..caf6623e2 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -32,7 +32,14 @@  #define	I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0)  #define	I2C_ADDR_TX_DB  (I2C_DEV_EEPROM | 0x4)  #define	I2C_ADDR_RX_DB  (I2C_DEV_EEPROM | 0x5) + +//////////////////////////////////////////////////////////////////////// +// EEPROM Layout  //////////////////////////////////////////////////////////////////////// +#define EE_MBOARD_REV_LSB  0x00 //1 byte +#define EE_MBOARD_REV_MSB  0x01 //1 byte +#define EE_MBOARD_MAC_ADDR 0x02 //6 bytes +#define EE_MBOARD_IP_ADDR  0x0C //uint32, big-endian  /*!   * The usrp2 interface class: diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 1dde8c054..af3ec216a 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -72,7 +72,7 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){      //send a hello control packet      usrp2_ctrl_data_t ctrl_data_out;      ctrl_data_out.proto_ver = htonl(USRP2_PROTO_VERSION); -    ctrl_data_out.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); +    ctrl_data_out.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO);      udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out)));      //loop and recieve until the timeout @@ -83,7 +83,7 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){          if (len >= sizeof(usrp2_ctrl_data_t)){              //handle the received data              switch(ntohl(ctrl_data_in.id)){ -            case USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE: +            case USRP2_CTRL_ID_WAZZUP_DUDE:                  //make a boost asio ipv4 with the raw addr in host byte order                  boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr));                  device_addr_t new_addr; @@ -147,6 +147,9 @@ usrp2_impl::usrp2_impl(      //make a new interface for usrp2 stuff      _iface = usrp2_iface::make(ctrl_transport); +    _clock_ctrl = clock_ctrl::make(_iface); +    _codec_ctrl = codec_ctrl::make(_iface); +    _serdes_ctrl = serdes_ctrl::make(_iface);      //load the allowed decim/interp rates      //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) @@ -207,14 +210,6 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){          val = prop_names_t(1, "");          return; -    case DEVICE_PROP_MAX_RX_SAMPLES: -        val = size_t(_max_rx_samples_per_packet); -        return; - -    case DEVICE_PROP_MAX_TX_SAMPLES: -        val = size_t(_max_tx_samples_per_packet); -        return; -      default: UHD_THROW_PROP_GET_ERROR();      }  } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 1c9387744..7948a2069 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -19,7 +19,9 @@  #define INCLUDED_USRP2_IMPL_HPP  #include "usrp2_iface.hpp" -#include "clock_control.hpp" +#include "clock_ctrl.hpp" +#include "codec_ctrl.hpp" +#include "serdes_ctrl.hpp"  #include <uhd/usrp/usrp2.hpp>  #include <uhd/types/dict.hpp>  #include <uhd/types/otw_type.hpp> @@ -31,6 +33,7 @@  #include <uhd/transport/vrt.hpp>  #include <uhd/transport/udp_zero_copy.hpp>  #include <uhd/usrp/dboard_manager.hpp> +#include "../../transport/vrt_packet_handler.hpp"  /*!   * Make a usrp2 dboard interface. @@ -40,7 +43,7 @@   */  uhd::usrp::dboard_iface::sptr make_usrp2_dboard_iface(      usrp2_iface::sptr iface, -    clock_control::sptr clk_ctrl +    clock_ctrl::sptr clk_ctrl  );  /*! @@ -101,8 +104,24 @@ public:      ~usrp2_impl(void);      //the io interface -    size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &); -    size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &); +    size_t get_max_send_samps_per_packet(void) const{ +        return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size(); +    } +    size_t send( +        const boost::asio::const_buffer &, +        const uhd::tx_metadata_t &, +        const uhd::io_type_t &, +        uhd::device::send_mode_t +    ); +    size_t get_max_recv_samps_per_packet(void) const{ +        return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size(); +    } +    size_t recv( +        const boost::asio::mutable_buffer &, +        uhd::rx_metadata_t &, +        const uhd::io_type_t &, +        uhd::device::recv_mode_t +    );  private:      double get_master_clock_freq(void){ @@ -114,28 +133,29 @@ private:      void set(const wax::obj &, const wax::obj &);      //interfaces -    clock_control::sptr _clk_ctrl;      usrp2_iface::sptr _iface; +    clock_ctrl::sptr _clock_ctrl; +    codec_ctrl::sptr _codec_ctrl; +    serdes_ctrl::sptr _serdes_ctrl; -    //the raw io interface (samples are in the usrp2 native format) -    void recv_raw(uhd::rx_metadata_t &); -    uhd::dict<boost::uint32_t, size_t> _tx_stream_id_to_packet_seq; -    uhd::dict<boost::uint32_t, size_t> _rx_stream_id_to_packet_seq; +    /******************************************************************* +     * Deal with the rx and tx packet sizes +     ******************************************************************/      static const size_t _mtu = 1500; //FIXME we have no idea      static const size_t _hdrs = (2 + 14 + 20 + 8); //size of headers (pad, eth, ip, udp) -    static const size_t _max_rx_samples_per_packet = -        (_mtu - _hdrs)/sizeof(boost::uint32_t) - -        USRP2_HOST_RX_VRT_HEADER_WORDS32 - -        USRP2_HOST_RX_VRT_TRAILER_WORDS32 +    static const size_t _max_rx_bytes_per_packet = +        _mtu - _hdrs - +        USRP2_HOST_RX_VRT_HEADER_WORDS32*sizeof(boost::uint32_t) - +        USRP2_HOST_RX_VRT_TRAILER_WORDS32*sizeof(boost::uint32_t)      ; -    static const size_t _max_tx_samples_per_packet = -        (_mtu - _hdrs)/sizeof(boost::uint32_t) - -        uhd::transport::vrt::max_header_words32 +    static const size_t _max_tx_bytes_per_packet = +        _mtu - _hdrs - +        uhd::transport::vrt::max_header_words32*sizeof(boost::uint32_t)      ; -    uhd::transport::managed_recv_buffer::sptr _rx_smart_buff; -    boost::asio::const_buffer _rx_copy_buff; -    size_t _fragment_offset_in_samps; -    uhd::otw_type_t _otw_type; + +    vrt_packet_handler::recv_state _packet_handler_recv_state; +    vrt_packet_handler::send_state _packet_handler_send_state; +    uhd::otw_type_t _rx_otw_type, _tx_otw_type;      void io_init(void);      //udp transports for control and data @@ -149,6 +169,7 @@ private:      //rx and tx dboard methods and objects      uhd::usrp::dboard_manager::sptr _dboard_manager; +    uhd::usrp::dboard_iface::sptr _dboard_iface;      void dboard_init(void);      //properties for the mboard diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 0e2a18756..0f675357b 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -64,7 +64,23 @@  /////////////////////////////////////////////////  // Misc Control  //////////////////////////////////////////////// -#define FR_CLOCK_CONTROL _SR_ADDR(0) +#define FR_MISC_CTRL_CLOCK           _SR_ADDR(0) +#define FR_MISC_CTRL_SERDES          _SR_ADDR(1) +#define FR_MISC_CTRL_ADC             _SR_ADDR(2) +#define FR_MISC_CTRL_LEDS            _SR_ADDR(3) +#define FR_MISC_CTRL_PHY             _SR_ADDR(4) // LSB is reset line to eth phy +#define FR_MISC_CTRL_DBG_MUX         _SR_ADDR(5) +#define FR_MISC_CTRL_RAM_PAGE        _SR_ADDR(6) // FIXME should go somewhere else... +#define FR_MISC_CTRL_FLUSH_ICACHE    _SR_ADDR(7) // Flush the icache +#define FR_MISC_CTRL_LED_SRC         _SR_ADDR(8) // HW or SW control for LEDs + +#define FRF_MISC_CTRL_SERDES_ENABLE 8 +#define FRF_MISC_CTRL_SERDES_PRBSEN 4 +#define FRF_MISC_CTRL_SERDES_LOOPEN 2 +#define FRF_MISC_CTRL_SERDES_RXEN   1 + +#define FRF_MISC_CTRL_ADC_ON  0x0F +#define FRF_MISC_CTRL_ADC_OFF 0x00  /////////////////////////////////////////////////  // VITA49 64 bit time (write only) @@ -188,7 +204,7 @@  #define FR_GPIO_RX_SEL     FR_GPIO_BASE + 12 // 16 2-bit fields select which source goes to RX DB  // each 2-bit sel field is layed out this way -#define FRF_GPIO_SEL_SW        0 // if pin is an output, set by software in the io reg +#define FRF_GPIO_SEL_GPIO      0 // if pin is an output, set by GPIO register  #define FRF_GPIO_SEL_ATR       1 // if pin is an output, set by ATR logic  #define FRF_GPIO_SEL_DEBUG_0   2 // if pin is an output, debug lines from FPGA fabric  #define FRF_GPIO_SEL_DEBUG_1   3 // if pin is an output, debug lines from FPGA fabric @@ -207,4 +223,25 @@  #define FR_ATR_FULL_TXSIDE  FR_ATR_BASE + 12  #define FR_ATR_FULL_RXSIDE  FR_ATR_BASE + 14 +/////////////////////////////////////////////////// +// VITA RX CTRL regs +/////////////////////////////////////////////////// +// The following 3 are logically a single command register. +// They are clocked into the underlying fifo when time_ticks is written. +#define FR_RX_CTRL_STREAM_CMD        _SR_ADDR(SR_RX_CTRL + 0) // {now, chain, num_samples(30) +#define FR_RX_CTRL_TIME_SECS         _SR_ADDR(SR_RX_CTRL + 1) +#define FR_RX_CTRL_TIME_TICKS        _SR_ADDR(SR_RX_CTRL + 2) + +#define FR_RX_CTRL_CLEAR_OVERRUN     _SR_ADDR(SR_RX_CTRL + 3) // write anything to clear overrun +#define FR_RX_CTRL_VRT_HEADER        _SR_ADDR(SR_RX_CTRL + 4) // word 0 of packet.  FPGA fills in packet counter +#define FR_RX_CTRL_VRT_STREAM_ID     _SR_ADDR(SR_RX_CTRL + 5) // word 1 of packet. +#define FR_RX_CTRL_VRT_TRAILER       _SR_ADDR(SR_RX_CTRL + 6) +#define FR_RX_CTRL_NSAMPS_PER_PKT    _SR_ADDR(SR_RX_CTRL + 7) +#define FR_RX_CTRL_NCHANNELS         _SR_ADDR(SR_RX_CTRL + 8) // 1 in basic case, up to 4 for vector sources + +//helpful macros for dealing with stream cmd +#define FR_RX_CTRL_MAX_SAMPS_PER_CMD 0x1fffffff +#define FR_RX_CTRL_MAKE_CMD(nsamples, now, chain, reload) \ +  ((((now) & 0x1) << 31) | (((chain) & 0x1) << 30) | (((reload) & 0x1) << 29) | ((nsamples) & 0x1fffffff)) +  #endif /* INCLUDED_USRP2_REGS_HPP */ diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index e70934b8c..23255b58c 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -49,8 +49,10 @@ public:      void write_aux_dac(unit_t, int, float);      float read_aux_adc(unit_t, int); +    void set_pin_ctrl(unit_t, boost::uint16_t);      void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);      void set_gpio_ddr(unit_t, boost::uint16_t); +    void write_gpio(unit_t, boost::uint16_t);      boost::uint16_t read_gpio(unit_t);      void write_i2c(boost::uint8_t, const byte_vector_t &); @@ -111,29 +113,41 @@ void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){  /***********************************************************************   * GPIO   **********************************************************************/ -void usrp_e_dboard_iface::set_gpio_ddr(unit_t bank, boost::uint16_t value){ -    //define mapping of gpio bank to register address -    static const uhd::dict<unit_t, boost::uint32_t> bank_to_addr = map_list_of -        (UNIT_RX, UE_REG_GPIO_RX_DDR) -        (UNIT_TX, UE_REG_GPIO_TX_DDR) -    ; -    _iface->poke16(bank_to_addr[bank], value); +void usrp_e_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){ +    UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption +    switch(unit){ +    case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_SEL, value); return; +    case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_SEL, value); return; +    }  } -boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t bank){ -    //define mapping of gpio bank to register address -    static const uhd::dict<unit_t, boost::uint32_t> bank_to_addr = map_list_of -        (UNIT_RX, UE_REG_GPIO_RX_IO) -        (UNIT_TX, UE_REG_GPIO_TX_IO) -    ; -    return _iface->peek16(bank_to_addr[bank]); +void usrp_e_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ +    switch(unit){ +    case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_DDR, value); return; +    case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_DDR, value); return; +    } +} + +void usrp_e_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value){ +    switch(unit){ +    case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_IO, value); return; +    case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_IO, value); return; +    } +} + +boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t unit){ +    switch(unit){ +    case UNIT_RX: return _iface->peek16(UE_REG_GPIO_RX_IO); +    case UNIT_TX: return _iface->peek16(UE_REG_GPIO_TX_IO); +    } +    UHD_ASSERT_THROW(false);  } -void usrp_e_dboard_iface::set_atr_reg(unit_t bank, atr_reg_t atr, boost::uint16_t value){ -    //define mapping of bank to atr regs to register address +void usrp_e_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ +    //define mapping of unit to atr regs to register address      static const uhd::dict<          unit_t, uhd::dict<atr_reg_t, boost::uint32_t> -    > bank_to_atr_to_addr = map_list_of +    > unit_to_atr_to_addr = map_list_of          (UNIT_RX, map_list_of              (ATR_REG_IDLE,        UE_REG_ATR_IDLE_RXSIDE)              (ATR_REG_TX_ONLY,     UE_REG_ATR_INTX_RXSIDE) @@ -147,7 +161,7 @@ void usrp_e_dboard_iface::set_atr_reg(unit_t bank, atr_reg_t atr, boost::uint16_              (ATR_REG_FULL_DUPLEX, UE_REG_ATR_FULL_TXSIDE)          )      ; -    _iface->poke16(bank_to_atr_to_addr[bank][atr], value); +    _iface->poke16(unit_to_atr_to_addr[unit][atr], value);  }  /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 4f7361eca..4a398e21c 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -117,14 +117,6 @@ void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){          val = prop_names_t(1, ""); //vector of size 1 with empty string          return; -    case DEVICE_PROP_MAX_RX_SAMPLES: -        val = size_t(_max_num_samples); -        return; - -    case DEVICE_PROP_MAX_TX_SAMPLES: -        val = size_t(_max_num_samples); -        return; -      default: UHD_THROW_PROP_GET_ERROR();      }  } @@ -142,7 +134,8 @@ void usrp_e_impl::set(const wax::obj &, const wax::obj &){  size_t usrp_e_impl::send(      const boost::asio::const_buffer &,      const uhd::tx_metadata_t &, -    const io_type_t & +    const io_type_t &, +    send_mode_t  ){      if (true){          throw std::runtime_error(str(boost::format("usrp-e send: cannot handle type \"%s\"") % "")); @@ -153,7 +146,8 @@ size_t usrp_e_impl::send(  size_t usrp_e_impl::recv(      const boost::asio::mutable_buffer &,      uhd::rx_metadata_t &, -    const io_type_t & +    const io_type_t &, +    recv_mode_t  ){      if (true){          throw std::runtime_error(str(boost::format("usrp-e recv: cannot handle type \"%s\"") % "")); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 59f80c70c..a2cdbc31e 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -89,8 +89,10 @@ public:      ~usrp_e_impl(void);      //the io interface -    size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &); -    size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &); +    size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t); +    size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t); +    size_t get_max_send_samps_per_packet(void) const{return _max_num_samples;} +    size_t get_max_recv_samps_per_packet(void) const{return _max_num_samples;}  private:      static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index 7f35212f4..51a47f061 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -78,11 +78,13 @@  #define UE_REG_GPIO_RX_DBG     UE_REG_GPIO_BASE + 12  #define UE_REG_GPIO_TX_DBG     UE_REG_GPIO_BASE + 14 -// each 2-bit sel field is layed out this way -#define GPIO_SEL_SW	   0 // if pin is an output, set by software in the io reg -#define	GPIO_SEL_ATR	   1 // if pin is an output, set by ATR logic -#define	GPIO_SEL_DEBUG_0   0 // if pin is an output, debug lines from FPGA fabric -#define	GPIO_SEL_DEBUG_1   1 // if pin is an output, debug lines from FPGA fabric +//possible bit values for sel when dbg is 0: +#define GPIO_SEL_SW    0 // if pin is an output, set by software in the io reg +#define GPIO_SEL_ATR   1 // if pin is an output, set by ATR logic + +//possible bit values for sel when dbg is 1: +#define GPIO_SEL_DEBUG_0   0 // if pin is an output, debug lines from FPGA fabric +#define GPIO_SEL_DEBUG_1   1 // if pin is an output, debug lines from FPGA fabric  //////////////////////////////////////////////////// | 
