diff options
| author | Josh Blum <josh@joshknows.com> | 2011-01-30 20:39:26 -0800 | 
|---|---|---|
| committer | Josh Blum <josh@joshknows.com> | 2011-01-30 20:39:26 -0800 | 
| commit | 8aea3fb21dda08bcb64ff00a07de448615818a98 (patch) | |
| tree | 17de294c51caa4497ac66c2e52b4cbdec33a7b1b | |
| parent | e5e02b75b08d6129001acb57eb28a79515479bb5 (diff) | |
| download | uhd-8aea3fb21dda08bcb64ff00a07de448615818a98.tar.gz uhd-8aea3fb21dda08bcb64ff00a07de448615818a98.tar.bz2 uhd-8aea3fb21dda08bcb64ff00a07de448615818a98.zip | |
usrp-e100: work on clock control
| -rw-r--r-- | host/lib/usrp/usrp_e100/clock_ctrl.cpp | 123 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/clock_ctrl.hpp | 7 | 
2 files changed, 108 insertions, 22 deletions
| diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index 1fb1a7125..4048218f2 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -18,10 +18,12 @@  #include "clock_ctrl.hpp"  #include "ad9522_regs.hpp"  #include <uhd/utils/assert.hpp> +#include <uhd/utils/static.hpp>  #include <boost/cstdint.hpp>  #include "usrp_e100_regs.hpp" //spi slave constants  #include <boost/assign/list_of.hpp>  #include <boost/foreach.hpp> +#include <boost/format.hpp>  #include <utility>  #include <iostream> @@ -36,6 +38,62 @@ template <typename div_type, typename bypass_type> static void set_clock_divider  }  /*********************************************************************** + * Clock rate calculation stuff: + *   Using the internal VCO between 1400 and 1800 MHz + **********************************************************************/ +struct clock_settings_type{ +    size_t ref_clock_doubler, r_counter, a_counter, b_counter, prescaler, vco_divider, clk_divider; +    size_t get_n_counter(void) const{return prescaler * b_counter + a_counter;} +    double get_ref_rate(void) const{return 10e6 * ref_clock_doubler;} +    double get_vco_rate(void) const{return get_ref_rate()/r_counter * get_n_counter();} +    double get_clk_rate(void) const{return get_vco_rate()/vco_divider;} +    double get_out_rate(void) const{return get_clk_rate()/clk_divider;} +    std::string to_pp_string(void) const{ +        return str(boost::format( +            "  r_counter: %d\n" +            "  a_counter: %d\n" +            "  b_counter: %d\n" +            "  prescaler: %d\n" +            "  vco_divider: %d\n" +            "  clk_divider: %d\n" +            "  vco_rate: %fMHz\n" +            "  clk_rate: %fMHz\n" +            "  out_rate: %fMHz\n" +            ) +            % r_counter +            % a_counter +            % b_counter +            % prescaler +            % vco_divider +            % clk_divider +            % (get_vco_rate()/1e6) +            % (get_clk_rate()/1e6) +            % (get_out_rate()/1e6) +        ); +    } +}; + +UHD_SINGLETON_FCN(std::vector<clock_settings_type>, get_clock_settings); + +UHD_STATIC_BLOCK(libuhd_usrp_e100_reg_clock_rates){ +    clock_settings_type cs; +    cs.ref_clock_doubler = 2; //always doubling +    cs.prescaler = 8; //set to 8 when input is under 2400 MHz + +    for (cs.r_counter = 1; cs.r_counter <= 1; cs.r_counter++){ +    for (cs.b_counter = 3; cs.b_counter <= 10; cs.b_counter++){ +    for (cs.a_counter = 0; cs.a_counter <= 10; cs.a_counter++){ +    for (cs.vco_divider = 2; cs.vco_divider <= 6; cs.vco_divider++){ +    for (cs.clk_divider = 1; cs.clk_divider <= 32; cs.clk_divider++){ +        if (cs.get_vco_rate() > 1800e6) continue; +        if (cs.get_vco_rate() < 1400e6) continue; +        if (cs.get_out_rate() < 32e6) continue; //lowest we allow for GPMC interface +        //std::cout << (cs.get_out_rate()/1e6) << std::endl; +        get_clock_settings().push_back(cs); +    }}}}} +} + +/***********************************************************************   * Constants   **********************************************************************/  static const bool enable_test_clock = false; @@ -72,25 +130,45 @@ public:          _ad9522_regs.ld_pin_control = 0x00; //dld          _ad9522_regs.refmon_pin_control = 0x12; //show ref2 -        _ad9522_regs.enable_ref2 = 1; -        _ad9522_regs.enable_ref1 = 0; -        _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; +        this->use_internal_ref(); -        _ad9522_regs.set_r_counter(r_counter); -        _ad9522_regs.a_counter = a_counter; -        _ad9522_regs.set_b_counter(b_counter); +        this->set_fpga_clock_rate(64e6); //initialize to something + +        this->enable_rx_dboard_clock(false); +        this->enable_tx_dboard_clock(false); +    } + +    ~usrp_e100_clock_ctrl_impl(void){ +        this->enable_rx_dboard_clock(false); +        this->enable_tx_dboard_clock(false); +    } + +    void set_clock_settings_with_internal_vco(const clock_settings_type &cs){ +        _ad9522_regs.enable_clock_doubler = (cs.ref_clock_doubler == 2)? 1 : 0; + +        _ad9522_regs.set_r_counter(cs.r_counter); +        _ad9522_regs.a_counter = cs.a_counter; +        _ad9522_regs.set_b_counter(cs.b_counter); +        UHD_ASSERT_THROW(cs.prescaler == 8); //assumes this below:          _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9;          _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL;          _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA;          _ad9522_regs.vco_calibration_now = 1; //calibrate it! -        _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; +        switch(cs.vco_divider){ +        case 1: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV1; break; +        case 2: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV2; break; +        case 3: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV3; break; +        case 4: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV4; break; +        case 5: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; break; +        case 6: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV6; break; +        }          _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO;          //setup fpga master clock          _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; -        set_clock_divider(fpga_clock_divider, +        set_clock_divider(cs.clk_divider,              _ad9522_regs.divider0_low_cycles,              _ad9522_regs.divider0_high_cycles,              _ad9522_regs.divider0_bypass @@ -98,7 +176,7 @@ public:          //setup codec clock          _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; -        set_clock_divider(codec_clock_divider, +        set_clock_divider(cs.clk_divider,              _ad9522_regs.divider1_low_cycles,              _ad9522_regs.divider1_high_cycles,              _ad9522_regs.divider1_bypass @@ -125,21 +203,22 @@ public:              }          }          this->latch_regs(); -        //test read: -        //boost::uint32_t reg = _ad9522_regs.get_read_reg(0x01b); -        //boost::uint32_t result = _iface->transact_spi( -        //    UE_SPI_SS_AD9522, -        //    spi_config_t::EDGE_RISE, -        //    reg, 24, true /*no*/ -        //); -        //std::cout << "result " << std::hex << result << std::endl; -        this->enable_rx_dboard_clock(false); -        this->enable_tx_dboard_clock(false);      } -    ~usrp_e100_clock_ctrl_impl(void){ -        this->enable_rx_dboard_clock(false); -        this->enable_tx_dboard_clock(false); +    void set_fpga_clock_rate(double rate){ +        if (rate == 61.44e6){ +            //TODO special settings for external VCXO +        } +        else{ +            BOOST_FOREACH(const clock_settings_type &cs, get_clock_settings()){ +                if (rate != cs.get_out_rate()) continue; +                std::cout << "USRP-E100 clock control:" << std::endl << cs.to_pp_string() << std::endl; +                set_clock_settings_with_internal_vco(cs); +            } +            throw std::runtime_error(str(boost::format( +                "USRP-E100 clock control: could not find settings for clock rate %fMHz" +            ) % (rate/1e6))); +        }      }      double get_fpga_clock_rate(void){ diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.hpp b/host/lib/usrp/usrp_e100/clock_ctrl.hpp index d613d1473..1f9960ce4 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.hpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.hpp @@ -40,6 +40,13 @@ public:      static sptr make(usrp_e100_iface::sptr iface);      /*! +     * Set the rate of the fpga clock line. +     * Throws if rate is not valid. +     * \param rate the new rate in Hz +     */ +    virtual void set_fpga_clock_rate(double rate) = 0; + +    /*!       * Get the rate of the fpga clock line.       * \return the fpga clock rate in Hz       */ | 
