diff options
| author | Nick Foster <nick@nerdnetworks.org> | 2010-07-26 16:33:17 -0700 | 
|---|---|---|
| committer | Nick Foster <nick@nerdnetworks.org> | 2010-07-26 16:33:17 -0700 | 
| commit | d8f3980e45458cf68c8efaa029e492a1b8d08354 (patch) | |
| tree | cf6a19cf89117483ffc3dd4901d303d2398a205f | |
| parent | 7aec87d83f9aea23e7e9c71cdfe26aab6105f43c (diff) | |
| download | uhd-d8f3980e45458cf68c8efaa029e492a1b8d08354.tar.gz uhd-d8f3980e45458cf68c8efaa029e492a1b8d08354.tar.bz2 uhd-d8f3980e45458cf68c8efaa029e492a1b8d08354.zip | |
Host-side changes to work with the USRP2+.
Change summary:
Added clock register selection between USRP2/USRP2+
Added memory map selection between USRP2/USRP2+
Added ADS62P44 support for USRP2+
| -rw-r--r-- | host/lib/ic_reg_maps/CMakeLists.txt | 5 | ||||
| -rwxr-xr-x | host/lib/ic_reg_maps/gen_ads62p44_regs.py | 124 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/clock_ctrl.cpp | 105 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/codec_ctrl.cpp | 32 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/dboard_iface.cpp | 26 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/dboard_impl.cpp | 12 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 12 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 51 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/serdes_ctrl.cpp | 4 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_clk_regs.hpp | 63 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 13 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.hpp | 37 | 
13 files changed, 382 insertions, 103 deletions
| diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt index ba1bbc9f0..39f26a5a6 100644 --- a/host/lib/ic_reg_maps/CMakeLists.txt +++ b/host/lib/ic_reg_maps/CMakeLists.txt @@ -63,3 +63,8 @@ LIBUHD_PYTHON_GEN_SOURCE(      ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad9522_regs.py      ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad9522_regs.hpp  ) + +LIBUHD_PYTHON_GEN_SOURCE( +    ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ads62p44_regs.py +    ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ads62p44_regs.hpp +) diff --git a/host/lib/ic_reg_maps/gen_ads62p44_regs.py b/host/lib/ic_reg_maps/gen_ads62p44_regs.py new file mode 100755 index 000000000..f0a84d940 --- /dev/null +++ b/host/lib/ic_reg_maps/gen_ads62p44_regs.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# +# 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/>. +# + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_TMPL="""\ +######################################################################## +## address 0 +######################################################################## +reset                   0[1]     0       +serial_readout          0[0]     0       +######################################################################## +## address 16 +######################################################################## +clkout_strength         16[6:7]   0      weaker=1, default=0, stronger=3 +######################################################################## +## address 17 +######################################################################## +dataout_strength        17[0:1]   0      weaker=1, default=0, stronger=3, maximum=2 +lvds_current            17[2:3]   0      3_5ma, 2_5ma, 4_5ma, 1_75ma +lvds_current_double     17[4:5]   0      default, dblclk, dbldataclock +######################################################################## +## address 18 +######################################################################## +lvds_clk_term           18[0:2]   0      none, 300, 180, 110, 150, 100, 81, 60 +lvds_data_term          18[3:5]   0      none, 300, 180, 110, 150, 100, 81, 60 +######################################################################## +## address 19 +######################################################################## +offset_freeze           19[4]     0 +######################################################################## +## address 20 +######################################################################## +power_down              20[0:2]   0      normal, a_dis, b_dis, ab_dis, global_pd, a_sby, b_sby, mux +ref_select              20[3]     0      internal, external +coarse_gain             20[4]     0      0db, 3_5db +output_interface        20[5]     0      cmos, lvds +override                20[7]     0 +######################################################################## +## address 22 +######################################################################## +test_patterns           22[0:2]   0      normal, zeros, ones, toggle, ramp, custom +lvds_bytewise           22[3]     0 +data_format             22[4]     0      twos_complement, binary +######################################################################## +## address 23 +######################################################################## +fine_gain               23[0:3]   0 +######################################################################## +## address 24 and 25 +######################################################################## +custom_low              24[0:7]   0 +custom_high             25[0:5]   0 +######################################################################## +## address 26 +######################################################################## +gain_correction         26[0:3]   0 +offset_tc               26[4:6]   0      1_1s, 0_55s, 0_27s, 0_13s, 2_15s, 4_3s +low_latency             26[7]     0 +######################################################################## +## address 27 +######################################################################## +decimation              27[0:2]   0      decimate_2, decimate_4, decimate_1, decimate_8 +odd_tap_enable          27[3]     0 +filter_enable           27[4]     0 +filter_coeff_sel        27[5]     0      predefined, userdefined +offset_enable           27[7]     0 +######################################################################## +## address 29 +######################################################################## +decimation_filter_bands 29[0:1]   0 +""" + +######################################################################## +# Template for methods in the body of the struct +######################################################################## +BODY_TMPL="""\ +boost::uint8_t get_reg(boost::uint8_t addr){ +    boost::uint8_t reg = 0; +    switch(addr){ +    #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) +    case $addr: +        #for $reg in filter(lambda r: r.get_addr() == addr, $regs) +        reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); +        #end for +        break; +    #end for +    } +    return reg; +} + +boost::uint16_t get_write_reg(boost::uint8_t addr){ +    return (boost::uint16_t(addr) << 8) | get_reg(addr); +} + +boost::uint16_t get_read_reg(boost::uint8_t addr){ +    return (boost::uint16_t(addr) << 8) | (1 << 7); +} +""" + +if __name__ == '__main__': +    import common; common.generate( +        name='ads62p44_regs', +        regs_tmpl=REGS_TMPL, +        body_tmpl=BODY_TMPL, +        file=__file__, +    ) diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index 99d0b8bdd..1da8f4419 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -34,4 +34,5 @@ LIBUHD_APPEND_SOURCES(      ${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 +    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_regs.cpp  ) diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index b9be037c0..5ed8ec079 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -18,6 +18,7 @@  #include "clock_ctrl.hpp"  #include "ad9510_regs.hpp"  #include "usrp2_regs.hpp" //spi slave constants +#include "usrp2_clk_regs.hpp"  #include <uhd/utils/assert.hpp>  #include <boost/cstdint.hpp> @@ -29,10 +30,12 @@ using namespace uhd;  class usrp2_clock_ctrl_impl : public usrp2_clock_ctrl{  public:      usrp2_clock_ctrl_impl(usrp2_iface::sptr iface){ -        _iface = iface; +        _iface = iface; //_iface has get_hw_rev(), which lets us know if it's a USRP2+ (>=0x80) or USRP2 (<0x80). + +        clk_regs = usrp2_clk_regs_t(_iface->get_hw_rev());          _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; -        this->write_reg(0x09); +        this->write_reg(clk_regs.pll_3);          // Setup the clock registers to 100MHz:          //  This was already done by the firmware (or the host couldnt communicate). @@ -42,20 +45,20 @@ public:          _ad9510_regs.pll_power_down = ad9510_regs_t::PLL_POWER_DOWN_NORMAL;          _ad9510_regs.prescaler_value = ad9510_regs_t::PRESCALER_VALUE_DIV2; -        this->write_reg(0x0A); +        this->write_reg(clk_regs.pll_4);          _ad9510_regs.acounter = 0; -        this->write_reg(0x04); +        this->write_reg(clk_regs.acounter);          _ad9510_regs.bcounter_msb = 0;          _ad9510_regs.bcounter_lsb = 5; -        this->write_reg(0x05); -        this->write_reg(0x06); +        this->write_reg(clk_regs.bcounter_msb); +        this->write_reg(clk_regs.bcounter_lsb);          _ad9510_regs.ref_counter_msb = 0;          _ad9510_regs.ref_counter_lsb = 1; // r divider = 1 -        this->write_reg(0x0B); -        this->write_reg(0x0C); +        this->write_reg(clk_regs.ref_counter_msb); +        this->write_reg(clk_regs.ref_counter_lsb);          /* regs will be updated in commands below */ @@ -76,11 +79,12 @@ public:      }      //uses output clock 7 (cmos) +    //this clock is the same between USRP2 and USRP2+ and so this fn does not get a switch statement      void enable_rx_dboard_clock(bool enb){          _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; -        this->write_reg(0x43); +        this->write_reg(clk_regs.output(clk_regs.rx_db));          this->update_regs();      } @@ -96,8 +100,8 @@ public:          _ad9510_regs.divider_low_cycles_out7 = low - 1;          _ad9510_regs.divider_high_cycles_out7 = high - 1;          //write the registers -        this->write_reg(0x56); -        this->write_reg(0x57); +        this->write_reg(clk_regs.div_lo(clk_regs.rx_db)); +        this->write_reg(clk_regs.div_hi(clk_regs.rx_db));          this->update_regs();      } @@ -107,29 +111,50 @@ public:          return rates;      } -    //uses output clock 6 (cmos) +    //uses output clock 6 (cmos) on USRP2 and output clock 5 (cmos) on USRP2+      void enable_tx_dboard_clock(bool enb){ -        _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; -        this->write_reg(0x42); +        switch(clk_regs.tx_db) { +        case 5: //USRP2+ +          _ad9510_regs.power_down_lvds_cmos_out5 = enb? 0 : 1; +          _ad9510_regs.lvds_cmos_select_out5 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_CMOS; +          _ad9510_regs.output_level_lvds_out5 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; +          break; +        case 6: //USRP2 +          _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; +          break; +        } + +        this->write_reg(clk_regs.output(clk_regs.tx_db));          this->update_regs();      }      void set_rate_tx_dboard_clock(double rate){          assert_has(get_rates_tx_dboard_clock(), rate, "tx dboard clock rate");          size_t divider = size_t(rate/get_master_clock_rate()); -        //bypass when the divider ratio is one -        _ad9510_regs.bypass_divider_out6 = (divider == 1)? 1 : 0;          //calculate the low and high dividers          size_t high = divider/2;          size_t low = divider - high; -        //set the registers (divider - 1) -        _ad9510_regs.divider_low_cycles_out6 = low - 1; -        _ad9510_regs.divider_high_cycles_out6 = high - 1; + +        switch(clk_regs.tx_db) { +        case 5: //USRP2+ +          _ad9510_regs.bypass_divider_out5 = (divider == 1)? 1 : 0; +          _ad9510_regs.divider_low_cycles_out5 = low - 1; +          _ad9510_regs.divider_high_cycles_out5 = high - 1; +          break; +        case 6: //USRP2 +          //bypass when the divider ratio is one +          _ad9510_regs.bypass_divider_out6 = (divider == 1)? 1 : 0; +          //set the registers (divider - 1) +          _ad9510_regs.divider_low_cycles_out6 = low - 1; +          _ad9510_regs.divider_high_cycles_out6 = high - 1; +          break; +        } +          //write the registers -        this->write_reg(0x54); -        this->write_reg(0x55); +        this->write_reg(clk_regs.div_hi(clk_regs.tx_db)); +        this->write_reg(clk_regs.div_lo(clk_regs.tx_db));          this->update_regs();      } @@ -147,7 +172,7 @@ public:              ad9510_regs_t::CHARGE_PUMP_MODE_3STATE ;          _ad9510_regs.pll_mux_control = ad9510_regs_t::PLL_MUX_CONTROL_DLD_HIGH;          _ad9510_regs.pfd_polarity = ad9510_regs_t::PFD_POLARITY_POS; -        this->write_reg(0x08); +        this->write_reg(clk_regs.pll_2);          this->update_regs();      } @@ -170,32 +195,44 @@ private:       */      void update_regs(void){          _ad9510_regs.update_registers = 1; -        this->write_reg(0x5a); +        this->write_reg(clk_regs.update);      }      //uses output clock 3 (pecl) +    //this is the same between USRP2 and USRP2+ and doesn't get a switch statement      void enable_dac_clock(bool enb){          _ad9510_regs.power_down_lvpecl_out3 = (enb)?              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->write_reg(clk_regs.output(clk_regs.dac)); +        this->write_reg(clk_regs.div_hi(clk_regs.dac));          this->update_regs();      } -    //uses output clock 4 (lvds) +    //uses output clock 4 (lvds) on USRP2 and output clock 2 (lvpecl) on USRP2+      void enable_adc_clock(bool enb){ -        _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); +        switch(clk_regs.adc) { +        case 2: +          _ad9510_regs.power_down_lvpecl_out2 = enb? ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_NORMAL : ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_SAFE_PD; +          _ad9510_regs.output_level_lvpecl_out2 = ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT2_500MV; +          _ad9510_regs.bypass_divider_out2 = 1; +          break; +        case 4: +          _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; +          break; +        } + +        this->write_reg(clk_regs.output(clk_regs.adc)); +        this->write_reg(clk_regs.div_hi(clk_regs.adc));          this->update_regs();      } +    usrp2_clk_regs_t clk_regs;      usrp2_iface::sptr _iface;      ad9510_regs_t _ad9510_regs;  }; diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index 32cc13ded..107894d2a 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -17,6 +17,7 @@  #include "codec_ctrl.hpp"  #include "ad9777_regs.hpp" +#include "ads62p44_regs.hpp"  #include "usrp2_regs.hpp"  #include <boost/cstdint.hpp>  #include <boost/foreach.hpp> @@ -57,7 +58,16 @@ public:          }          //power-up adc -        _iface->poke32(U2_REG_MISC_CTRL_ADC, U2_FLAG_MISC_CTRL_ADC_ON); +        if(_iface->get_hw_rev() < USRP2P_FIRST_HW_REV) { //if we're on a USRP2 +          _iface->poke32(_iface->regs.misc_ctrl_adc, U2_FLAG_MISC_CTRL_ADC_ON); +        } else { //we're on a USRP2+ +          _ads62p44_regs.reset = 1; +          this->send_ads62p44_reg(0x00); //issue a reset to the ADC +          //everything else should be pretty much default, i think +//          _ads62p44_regs.decimation = DECIMATION_DECIMATE_1; +           + +        }      }      ~usrp2_codec_ctrl_impl(void){ @@ -66,11 +76,21 @@ public:          this->send_ad9777_reg(0);          //power-down adc -        _iface->poke32(U2_REG_MISC_CTRL_ADC, U2_FLAG_MISC_CTRL_ADC_OFF); +        if(_iface->get_hw_rev() < USRP2P_FIRST_HW_REV) { //if we're on a USRP2 +          _iface->poke32(_iface->regs.misc_ctrl_adc, U2_FLAG_MISC_CTRL_ADC_OFF); +        } else { //we're on a USRP2+ +//          _ads62p44_regs.reset = 1; +//          this->send_ads62p44_reg(0x00); //issue a reset to the ADC +          //everything else should be pretty much default, i think +//          _ads62p44_regs.decimation = DECIMATION_DECIMATE_1; +           + +        }      }  private:      ad9777_regs_t _ad9777_regs; +    ads62p44_regs_t _ads62p44_regs;      usrp2_iface::sptr _iface;      void send_ad9777_reg(boost::uint8_t addr){ @@ -81,6 +101,14 @@ private:              reg, 16, false /*no rb*/          );      } + +    void send_ads62p44_reg(boost::uint8_t addr) { +        boost::uint16_t reg = _ads62p44_regs.get_write_reg(addr); +        _iface->transact_spi( +            SPI_SS_ADS62P44, spi_config_t::EDGE_RISE, +            reg, 16, false /*no rb*/ +        ); +    }  };  /*********************************************************************** diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index 6f2fb9396..5c81856bb 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -168,8 +168,8 @@ void usrp2_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){      //write the selection mux value to register      switch(unit){ -    case UNIT_RX: _iface->poke32(U2_REG_GPIO_RX_SEL, new_sels); return; -    case UNIT_TX: _iface->poke32(U2_REG_GPIO_TX_SEL, new_sels); return; +    case UNIT_RX: _iface->poke32(_iface->regs.gpio_rx_sel, new_sels); return; +    case UNIT_TX: _iface->poke32(_iface->regs.gpio_tx_sel, new_sels); return;      }  } @@ -177,18 +177,18 @@ void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){      _ddr_shadow = \          (_ddr_shadow & ~(0xffff << unit_to_shift[unit])) |          (boost::uint32_t(value) << unit_to_shift[unit]); -    _iface->poke32(U2_REG_GPIO_DDR, _ddr_shadow); +    _iface->poke32(_iface->regs.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(U2_REG_GPIO_IO, _gpio_shadow); +    _iface->poke32(_iface->regs.gpio_io, _gpio_shadow);  }  boost::uint16_t usrp2_dboard_iface::read_gpio(unit_t unit){ -    return boost::uint16_t(_iface->peek32(U2_REG_GPIO_IO) >> unit_to_shift[unit]); +    return boost::uint16_t(_iface->peek32(_iface->regs.gpio_io) >> unit_to_shift[unit]);  }  void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ @@ -197,16 +197,16 @@ void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t          unit_t, uhd::dict<atr_reg_t, boost::uint32_t>      > unit_to_atr_to_addr = map_list_of          (UNIT_RX, map_list_of -            (ATR_REG_IDLE,        U2_REG_ATR_IDLE_RXSIDE) -            (ATR_REG_TX_ONLY,     U2_REG_ATR_INTX_RXSIDE) -            (ATR_REG_RX_ONLY,     U2_REG_ATR_INRX_RXSIDE) -            (ATR_REG_FULL_DUPLEX, U2_REG_ATR_FULL_RXSIDE) +            (ATR_REG_IDLE,        _iface->regs.atr_idle_rxside) +            (ATR_REG_TX_ONLY,     _iface->regs.atr_intx_rxside) +            (ATR_REG_RX_ONLY,     _iface->regs.atr_inrx_rxside) +            (ATR_REG_FULL_DUPLEX, _iface->regs.atr_full_rxside)          )          (UNIT_TX, map_list_of -            (ATR_REG_IDLE,        U2_REG_ATR_IDLE_TXSIDE) -            (ATR_REG_TX_ONLY,     U2_REG_ATR_INTX_TXSIDE) -            (ATR_REG_RX_ONLY,     U2_REG_ATR_INRX_TXSIDE) -            (ATR_REG_FULL_DUPLEX, U2_REG_ATR_FULL_TXSIDE) +            (ATR_REG_IDLE,        _iface->regs.atr_idle_txside) +            (ATR_REG_TX_ONLY,     _iface->regs.atr_intx_txside) +            (ATR_REG_RX_ONLY,     _iface->regs.atr_inrx_txside) +            (ATR_REG_FULL_DUPLEX, _iface->regs.atr_full_txside)          )      ;      _iface->poke16(unit_to_atr_to_addr[unit][atr], value); diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 8942f9d31..07e36a21b 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -35,8 +35,8 @@ using namespace uhd::usrp;   **********************************************************************/  void usrp2_mboard_impl::dboard_init(void){      //read the dboard eeprom to extract the dboard ids -    _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); -    _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); +    _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(USRP2_I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); +    _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(USRP2_I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes()));      //create a new dboard interface and manager      _dboard_iface = make_usrp2_dboard_iface(_iface, _clock_ctrl); @@ -103,7 +103,7 @@ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){              UHD_ASSERT_THROW(_rx_subdevs_in_use.size() == 1);              wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0));              std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl; -            _iface->poke32(U2_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( +            _iface->poke32(_iface->regs.dsp_rx_mux, dsp_type1::calc_rx_mux_word(                  rx_subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()              ));          } @@ -111,7 +111,7 @@ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){      case DBOARD_PROP_DBOARD_ID:          _rx_db_eeprom.id = val.as<dboard_id_t>(); -        _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes()); +        _iface->write_eeprom(USRP2_I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes());          return;      default: UHD_THROW_PROP_SET_ERROR(); @@ -162,7 +162,7 @@ void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){              UHD_ASSERT_THROW(_tx_subdevs_in_use.size() == 1);              wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0));              std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl; -            _iface->poke32(U2_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( +            _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word(                  tx_subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()              ));          } @@ -170,7 +170,7 @@ void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){      case DBOARD_PROP_DBOARD_ID:          _tx_db_eeprom.id = val.as<dboard_id_t>(); -        _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes()); +        _iface->write_eeprom(USRP2_I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes());          return;      default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 7d9cdc441..936b1f7a2 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -86,7 +86,7 @@ void usrp2_mboard_impl::ddc_set(const wax::obj &key, const wax::obj &val){      case DSP_PROP_FREQ_SHIFT:{              double new_freq = val.as<double>(); -            _iface->poke32(U2_REG_DSP_RX_FREQ, +            _iface->poke32(_iface->regs.dsp_rx_freq,                  dsp_type1::calc_cordic_word_and_update(new_freq, get_master_clock_freq())              );              _ddc_freq = new_freq; //shadow @@ -98,11 +98,11 @@ void usrp2_mboard_impl::ddc_set(const wax::obj &key, const wax::obj &val){              _ddc_decim = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates);              //set the decimation -            _iface->poke32(U2_REG_DSP_RX_DECIM_RATE, dsp_type1::calc_cic_filter_word(_ddc_decim)); +            _iface->poke32(_iface->regs.dsp_rx_decim_rate, dsp_type1::calc_cic_filter_word(_ddc_decim));              //set the scaling              static const boost::int16_t default_rx_scale_iq = 1024; -            _iface->poke32(U2_REG_DSP_RX_SCALE_IQ, +            _iface->poke32(_iface->regs.dsp_rx_scale_iq,                  dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq)              );          } @@ -161,7 +161,7 @@ void usrp2_mboard_impl::duc_set(const wax::obj &key, const wax::obj &val){      case DSP_PROP_FREQ_SHIFT:{              double new_freq = val.as<double>(); -            _iface->poke32(U2_REG_DSP_TX_FREQ, +            _iface->poke32(_iface->regs.dsp_tx_freq,                  dsp_type1::calc_cordic_word_and_update(new_freq, get_master_clock_freq())              );              _duc_freq = new_freq; //shadow @@ -173,10 +173,10 @@ void usrp2_mboard_impl::duc_set(const wax::obj &key, const wax::obj &val){              _duc_interp = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates);              //set the interpolation -            _iface->poke32(U2_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_duc_interp)); +            _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_duc_interp));              //set the scaling -            _iface->poke32(U2_REG_DSP_TX_SCALE_IQ, dsp_type1::calc_iq_scale_word(_duc_interp)); +            _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_duc_interp));          }          return; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 7518d3114..938bf8466 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -45,8 +45,11 @@ usrp2_mboard_impl::usrp2_mboard_impl(      _iface = usrp2_iface::make(ctrl_transport);      //extract the mboard rev numbers -    _rev_lo = _iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_REV_LSB, 1).at(0); -    _rev_hi = _iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_REV_MSB, 1).at(0); +    _rev_lo = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_LSB, 1).at(0); +    _rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0); + +    //set the device revision (USRP2 or USRP2+) based on the above +    _iface->set_hw_rev((_rev_hi << 8) | _rev_lo);      //contruct the interfaces to mboard perifs      _clock_ctrl = usrp2_clock_ctrl::make(_iface); @@ -68,18 +71,18 @@ usrp2_mboard_impl::usrp2_mboard_impl(      }      //setup the vrt rx registers -    _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _io_helper.get_max_recv_samps_per_packet()); -    _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); -    _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset -    _iface->poke32(U2_REG_RX_CTRL_VRT_HEADER, 0 +    _iface->poke32(_iface->regs.rx_ctrl_nsamps_per_pkt, _io_helper.get_max_recv_samps_per_packet()); +    _iface->poke32(_iface->regs.rx_ctrl_nchannels, 1); +    _iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //reset +    _iface->poke32(_iface->regs.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(U2_REG_RX_CTRL_VRT_STREAM_ID, 0); -    _iface->poke32(U2_REG_RX_CTRL_VRT_TRAILER, 0); -    _iface->poke32(U2_REG_TIME64_TPS, size_t(get_master_clock_freq())); +    _iface->poke32(_iface->regs.rx_ctrl_vrt_stream_id, 0); +    _iface->poke32(_iface->regs.rx_ctrl_vrt_trailer, 0); +    _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq()));      //init the ddc      init_ddc_config(); @@ -129,13 +132,13 @@ void usrp2_mboard_impl::update_clock_config(void){      }      //set the pps flags -    _iface->poke32(U2_REG_TIME64_FLAGS, pps_flags); +    _iface->poke32(_iface->regs.time64_flags, pps_flags);      //clock source ref 10mhz      switch(_clock_config.ref_source){ -    case clock_config_t::REF_INT : _iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x10); break; -    case clock_config_t::REF_SMA : _iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); break; -    case clock_config_t::REF_MIMO: _iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15); break; +    case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break; +    case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; +    case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break;      default: throw std::runtime_error("usrp2: unhandled clock configuration reference source");      } @@ -146,22 +149,22 @@ void usrp2_mboard_impl::update_clock_config(void){  void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){      //set the ticks -    _iface->poke32(U2_REG_TIME64_TICKS, time_spec.get_tick_count(get_master_clock_freq())); +    _iface->poke32(_iface->regs.time64_ticks, time_spec.get_tick_count(get_master_clock_freq()));      //set the flags register      boost::uint32_t imm_flags = (now)? U2_FLAG_TIME64_LATCH_NOW : U2_FLAG_TIME64_LATCH_NEXT_PPS; -    _iface->poke32(U2_REG_TIME64_IMM, imm_flags); +    _iface->poke32(_iface->regs.time64_imm, imm_flags);      //set the seconds (latches in all 3 registers) -    _iface->poke32(U2_REG_TIME64_SECS, boost::uint32_t(time_spec.get_full_secs())); +    _iface->poke32(_iface->regs.time64_secs, boost::uint32_t(time_spec.get_full_secs()));  }  void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ -    _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word( +    _iface->poke32(_iface->regs.rx_ctrl_stream_cmd, dsp_type1::calc_stream_cmd_word(          stream_cmd, _io_helper.get_max_recv_samps_per_packet()      )); -    _iface->poke32(U2_REG_RX_CTRL_TIME_SECS,  boost::uint32_t(stream_cmd.time_spec.get_full_secs())); -    _iface->poke32(U2_REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); +    _iface->poke32(_iface->regs.rx_ctrl_time_secs,  boost::uint32_t(stream_cmd.time_spec.get_full_secs())); +    _iface->poke32(_iface->regs.rx_ctrl_time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq()));  }  /*********************************************************************** @@ -174,14 +177,14 @@ void usrp2_mboard_impl::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"){ -            byte_vector_t bytes = _iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_MAC_ADDR, 6); +            byte_vector_t bytes = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, 6);              val = mac_addr_t::from_bytes(bytes).to_string();              return;          }          if (key.as<std::string>() == "ip-addr"){              boost::asio::ip::address_v4::bytes_type bytes; -            std::copy(_iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_IP_ADDR, 4), bytes); +            std::copy(_iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, 4), bytes);              val = boost::asio::ip::address_v4(bytes).to_string();              return;          } @@ -244,7 +247,7 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){      case MBOARD_PROP_TIME_NOW:{              usrp2_iface::pair64 time64( -                _iface->peek64(U2_REG_TIME64_SECS_RB, U2_REG_TIME64_TICKS_RB) +                _iface->peek64(_iface->regs.time64_secs_rb, _iface->regs.time64_ticks_rb)              );              val = time_spec_t(                  time64.first, time64.second, get_master_clock_freq() @@ -264,14 +267,14 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){      if (key.type() == typeid(std::string)){          if (key.as<std::string>() == "mac-addr"){              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); +            _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, bytes);              return;          }          if (key.as<std::string>() == "ip-addr"){              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); +            _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, bytes);              return;          }      } diff --git a/host/lib/usrp/usrp2/serdes_ctrl.cpp b/host/lib/usrp/usrp2/serdes_ctrl.cpp index e83dceb96..1cda22f45 100644 --- a/host/lib/usrp/usrp2/serdes_ctrl.cpp +++ b/host/lib/usrp/usrp2/serdes_ctrl.cpp @@ -27,11 +27,11 @@ class usrp2_serdes_ctrl_impl : public usrp2_serdes_ctrl{  public:      usrp2_serdes_ctrl_impl(usrp2_iface::sptr iface){          _iface = iface; -        _iface->poke32(U2_REG_MISC_CTRL_SERDES, U2_FLAG_MISC_CTRL_SERDES_ENABLE | U2_FLAG_MISC_CTRL_SERDES_RXEN); +        _iface->poke32(_iface->regs.misc_ctrl_serdes, U2_FLAG_MISC_CTRL_SERDES_ENABLE | U2_FLAG_MISC_CTRL_SERDES_RXEN);      }      ~usrp2_serdes_ctrl_impl(void){ -        _iface->poke32(U2_REG_MISC_CTRL_SERDES, 0); //power-down +        _iface->poke32(_iface->regs.misc_ctrl_serdes, 0); //power-down      }  private: diff --git a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp new file mode 100644 index 000000000..d057fb342 --- /dev/null +++ b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp @@ -0,0 +1,63 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_USRP2_CLK_REGS_HPP +#define INCLUDED_USRP2_CLK_REGS_HPP + +#include "usrp2_regs.hpp" + +class usrp2_clk_regs_t { +public: +  usrp2_clk_regs_t(void) { ; } +  usrp2_clk_regs_t(int hw_rev) {    +    test = 0; +    fpga = 1; +    adc = (hw_rev>=USRP2P_FIRST_HW_REV) ? 2 : 4; +    dac = 3; +    serdes = (hw_rev>=USRP2P_FIRST_HW_REV) ? 4 : 2; //only used by usrp2+ +    tx_db = (hw_rev>=USRP2P_FIRST_HW_REV) ? 5 : 6; +    exp = (hw_rev>=USRP2P_FIRST_HW_REV) ? 6 : 5; +    rx_db = 7; +  } + +  static int output(int clknum) { return 0x3C + clknum; } +  static int div_lo(int clknum) { return 0x48 + 2 * clknum; } +  static int div_hi(int clknum) { return 0x49 + 2 * clknum; } + +  const static int acounter = 0x04; +  const static int bcounter_msb = 0x05; +  const static int bcounter_lsb = 0x06; +  const static int pll_1 = 0x07; +  const static int pll_2 = 0x08; +  const static int pll_3 = 0x09; +  const static int pll_4 = 0x0A; +  const static int ref_counter_msb = 0x0B; +  const static int ref_counter_lsb = 0x0C; +  const static int pll_5 = 0x0D; +  const static int update = 0x5A; + +  int test; +  int fpga; +  int adc; +  int dac; +  int serdes; +  int exp; +  int tx_db; +  int rx_db; +}; + +#endif //INCLUDED_USRP2_CLK_REGS_HPP diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index a21157d76..17ba75d85 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -193,6 +193,19 @@ public:          throw std::runtime_error("usrp2 no control response");      } + /*********************************************************************** +  * Get/set hardware revision +  **********************************************************************/ +    void set_hw_rev(int rev) { +        hw_rev = rev; +        regs = usrp2_get_regs(rev); //might be a better place to do this +    } +  +    int get_hw_rev(void) { +        return hw_rev; +    } + +  private:      //this lovely lady makes it all possible      udp_simple::sptr _ctrl_transport; diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 9cc32104e..b9f5f0fb8 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -25,22 +25,7 @@  #include <boost/cstdint.hpp>  #include <utility>  #include "fw_common.h" - -//////////////////////////////////////////////////////////////////////// -// I2C addresses -//////////////////////////////////////////////////////////////////////// -#define I2C_DEV_EEPROM  0x50 // 24LC02[45]:  7-bits 1010xxx -#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 +#include "usrp2_regs.hpp"  /*!   * The usrp2 interface class: @@ -118,6 +103,26 @@ public:          size_t num_bits,          bool readback      ) = 0; + +    /*! +     * Set the hardware revision number. Also selects the proper register set for the device. +     * \param rev the 16-bit revision +     */ +    virtual void set_hw_rev(int rev) = 0; + +    /*! Return the hardware revision number +     * \return hardware revision +     */ +    virtual int get_hw_rev(void) = 0; + +    /*! +     * Register map selected from USRP2/USRP2+. +     */ +    usrp2_regs_t regs; +    /*! +     * Hardware revision as returned by the device. +     */ +    int hw_rev;  };  #endif /* INCLUDED_USRP2_IFACE_HPP */ | 
