diff options
| author | Thomas Tsou <ttsou@vt.edu> | 2010-08-18 11:06:57 -0700 | 
|---|---|---|
| committer | Thomas Tsou <ttsou@vt.edu> | 2010-08-18 19:22:06 -0700 | 
| commit | 024377afa9628c282a5f7584ca5cc8991dd1296f (patch) | |
| tree | eab06d8b6e6a5c059090b19982867af431a5597f | |
| parent | e4c12fbfb2a928574b33260f04f9622e3c876700 (diff) | |
| download | uhd-024377afa9628c282a5f7584ca5cc8991dd1296f.tar.gz uhd-024377afa9628c282a5f7584ca5cc8991dd1296f.tar.bz2 uhd-024377afa9628c282a5f7584ca5cc8991dd1296f.zip | |
usrp1: Refactor mboard tuning code
| -rw-r--r-- | host/lib/usrp/usrp1/codec_ctrl.cpp | 164 | ||||
| -rw-r--r-- | host/lib/usrp/usrp1/codec_ctrl.hpp | 8 | ||||
| -rw-r--r-- | host/lib/usrp/usrp1/dsp_impl.cpp | 26 | ||||
| -rw-r--r-- | host/lib/usrp/usrp1/usrp1_impl.cpp | 8 | 
4 files changed, 92 insertions, 114 deletions
| diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 01617de94..419e4c5e2 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -17,6 +17,7 @@  #include "codec_ctrl.hpp"  #include "usrp_commands.h" +#include "clock_ctrl.hpp"  #include "ad9862_regs.hpp"  #include <uhd/types/dict.hpp>  #include <uhd/utils/assert.hpp> @@ -43,7 +44,9 @@ const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1);  class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl {  public:      //structors -    usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave); +    usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, +                          usrp1_clock_ctrl::sptr clock, +                          int spi_slave);      ~usrp1_codec_ctrl_impl(void);      //aux adc and dac control @@ -51,7 +54,7 @@ public:      void write_aux_dac(aux_dac_t which, float volts);      //duc control -    bool set_duc_freq(double freq); +    void set_duc_freq(double freq);      //pga gain control      void set_tx_pga_gain(float); @@ -61,25 +64,26 @@ public:  private:      usrp1_iface::sptr _iface; +    usrp1_clock_ctrl::sptr _clock_ctrl;      int _spi_slave;      ad9862_regs_t _ad9862_regs;      aux_adc_t _last_aux_adc_a, _last_aux_adc_b;      void send_reg(boost::uint8_t addr);      void recv_reg(boost::uint8_t addr); -    //FIXME: poison -    double _tx_freq[4]; -    unsigned int compute_freq_control_word_9862 (double master_freq, -                                                 double target_freq, -                                                 double *actual_freq); +    double coarse_tune(double codec_rate, double freq); +    double fine_tune(double codec_rate, double freq);  };  /***********************************************************************   * Codec Control Structors   **********************************************************************/ -usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave) +usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, +                                             usrp1_clock_ctrl::sptr clock, +                                             int spi_slave)  {      _iface = iface; +    _clock_ctrl = clock;      _spi_slave = spi_slave;      //soft reset @@ -324,118 +328,102 @@ void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr)  /***********************************************************************   * DUC tuning    **********************************************************************/ -unsigned int usrp1_codec_ctrl_impl::compute_freq_control_word_9862( -                    double master_freq, double target_freq, double *actual_freq) +double usrp1_codec_ctrl_impl::coarse_tune(double codec_rate, double freq)  { -    double sign = 1.0; -  -    if (target_freq < 0) -        sign = -1.0; -  -    int v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0)); -    *actual_freq = v * master_freq / pow (2.0, 24.0) * sign; -  -    std::cout << boost::format( -       "compute_freq_control_word_9862: target = %g  actual = %g  delta = %g  v = %8d\n" -    ) % target_freq % *actual_freq % (*actual_freq - target_freq) % v; -  -    return (unsigned int) v; -} +    double coarse_freq; -bool usrp1_codec_ctrl_impl::set_duc_freq(double freq) -{ -    int channel = 0; -    float dac_rate = 128e6; -  -    double coarse; - -    std::cout << "duc_freq: " << freq << std::endl; - -    // First coarse frequency -    double coarse_freq_1 = dac_rate / 8; -    // Second coarse frequency -    double coarse_freq_2 = dac_rate / 4; -    // Midpoint of [0 , freq1] range +    double coarse_freq_1 = codec_rate / 8; +    double coarse_freq_2 = codec_rate / 4;      double coarse_limit_1 = coarse_freq_1 / 2; -    // Midpoint of [freq1 , freq2] range      double coarse_limit_2 = (coarse_freq_1 + coarse_freq_2) / 2; -    // Highest meaningful frequency -    double high_limit = (double) 44e6 / 128e6 * dac_rate; +    double max_freq = coarse_freq_2 + .09375 * codec_rate; -    if (freq < -high_limit) {              // too low +    if (freq < -max_freq) {          return false;      } -    else if (freq < -coarse_limit_2) {     // For 64MHz: [-44, -24) +    else if (freq < -coarse_limit_2) {          _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT;          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; -        coarse = -coarse_freq_2; +        coarse_freq = -coarse_freq_2;      } -    else if (freq < -coarse_limit_1) {     // For 64MHz: [-24, -8) +    else if (freq < -coarse_limit_1) {          _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT;          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; -        coarse = -coarse_freq_1; +        coarse_freq = -coarse_freq_1;      } -    else if (freq < coarse_limit_1) {      // For 64MHz: [-8, 8) +    else if (freq < coarse_limit_1) {          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; -        coarse = 0;  +        coarse_freq = 0;       } -    else if (freq < coarse_limit_2) {      // For 64MHz: [8, 24) +    else if (freq < coarse_limit_2) {          _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT;          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; -        coarse = coarse_freq_1; +        coarse_freq = coarse_freq_1;      } -    else if (freq <= high_limit) {         // For 64MHz: [24, 44] +    else if (freq <= max_freq) {          _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT;          _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; -        coarse = coarse_freq_2; +        coarse_freq = coarse_freq_2;      } -    else {                                 // too high -        return false; +    else { +        return 0;       } -  -    double fine = freq - coarse; -  -    // Compute fine tuning word... -    // This assumes we're running the 4x on-chip interpolator. -    // (This is required to use the fine modulator.) -  -    unsigned int v = compute_freq_control_word_9862 (dac_rate / 4, fine, -                                                     &_tx_freq[channel]); - -    _tx_freq[channel] += coarse;         // adjust actual -     -    boost::uint8_t high; -    boost::uint8_t mid; -    boost::uint8_t low; -  -    high = (v >> 16) & 0xff; -    mid  = (v >>  8) & 0xff; -    low  = (v >>  0) & 0xff; -  -    // write the fine tuning word -    _ad9862_regs.ftw_23_16 = high; -    _ad9862_regs.ftw_15_8 = mid; -    _ad9862_regs.ftw_7_0 = low; -  -    _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; -  -    if (fine < 0) + +    return coarse_freq; +} + +double usrp1_codec_ctrl_impl::fine_tune(double codec_rate, double target_freq) +{ +    static const double scale_factor = std::pow(2.0, 24); + +    boost::uint32_t freq_word = boost::uint32_t( +        boost::math::round(abs((target_freq / codec_rate) * scale_factor))); + +    double actual_freq = freq_word * codec_rate / scale_factor; + +    if (target_freq < 0) {          _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_NEG_SHIFT; -    else +        actual_freq = -actual_freq;  +    } +    else {          _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_POS_SHIFT; -  +    }  + +    _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; +    _ad9862_regs.ftw_23_16 = (freq_word >> 16) & 0xff; +    _ad9862_regs.ftw_15_8  = (freq_word >>  8) & 0xff; +    _ad9862_regs.ftw_7_0   = (freq_word >>  0) & 0xff; + +    return actual_freq; +} + +void usrp1_codec_ctrl_impl::set_duc_freq(double freq) +{ +    double codec_rate = _clock_ctrl->get_master_clock_freq() * 2; +    double coarse_freq = coarse_tune(codec_rate, freq); +    double fine_freq = fine_tune(codec_rate / 4, freq - coarse_freq); + +    if (codec_debug) { +        std::cout << "ad9862 tuning result:" << std::endl; +        std::cout << "   requested:   " << freq << std::endl; +        std::cout << "   actual:      " << coarse_freq + fine_freq << std::endl; +        std::cout << "   coarse freq: " << coarse_freq << std::endl; +        std::cout << "   fine freq:   " << fine_freq << std::endl; +        std::cout << "   codec rate:  " << codec_rate << std::endl; +    }     +      this->send_reg(20);      this->send_reg(21);      this->send_reg(22);      this->send_reg(23); -  -    return true;   }  /***********************************************************************   * Codec Control Make   **********************************************************************/ -usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, int spi_slave) +usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, +                                              usrp1_clock_ctrl::sptr clock, +                                              int spi_slave)  { -    return sptr(new usrp1_codec_ctrl_impl(iface, spi_slave)); +    return sptr(new usrp1_codec_ctrl_impl(iface, clock, spi_slave));  } diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp index 6440f97d1..259d10ef4 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.hpp +++ b/host/lib/usrp/usrp1/codec_ctrl.hpp @@ -19,6 +19,7 @@  #define INCLUDED_USRP1_CODEC_CTRL_HPP  #include "usrp1_iface.hpp" +#include "clock_ctrl.hpp"  #include <uhd/types/ranges.hpp>  #include <boost/shared_ptr.hpp>  #include <boost/utility.hpp> @@ -41,7 +42,9 @@ public:       * \param spi_slave which spi device       * \return the clock control object       */ -    static sptr make(usrp1_iface::sptr iface, int spi_slave); +    static sptr make(usrp1_iface::sptr iface, +        usrp1_clock_ctrl::sptr clock, int spi_slave +    );      //! aux adc identifier constants      enum aux_adc_t{ @@ -87,7 +90,8 @@ public:      //! Get the RX PGA gain ('A' or 'B')      virtual float get_rx_pga_gain(char which) = 0; -    virtual bool set_duc_freq(double freq) = 0; +    //! Set the TX modulator frequency +    virtual void set_duc_freq(double freq) = 0;  };  #endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 0db3cb473..ce0c12e4b 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -73,31 +73,13 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val)  /***********************************************************************   * RX DDC Set   **********************************************************************/ -unsigned int compute_freq_word(double master, double target) -{ -    static const int NBITS = 14; -    int   v = (int) rint (target / master * pow(2.0, 32.0)); -  -    if (0) -      v = (v >> (32 - NBITS)) << (32 - NBITS);    // keep only top NBITS -  -    double actual_freq = v * master / pow(2.0, 32.0); -  -    if (0) std::cerr << boost::format( -        "compute_freq_control_word_fpga: target = %g  actual = %g  delta = %g\n" -    ) % target % actual_freq % (actual_freq - target); -  -    return (unsigned int) v; -} -  void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val)  {      switch(key.as<dsp_prop_t>()) {      case DSP_PROP_FREQ_SHIFT: {              double new_freq = val.as<double>(); -            boost::uint32_t hw_freq_word = compute_freq_word( -                              _clock_ctrl->get_master_clock_freq(), new_freq); -            _iface->poke32(FR_RX_FREQ_0, hw_freq_word); +            _iface->poke32(FR_RX_FREQ_0, +                -dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_master_clock_freq()));              _tx_dsp_freq = new_freq;              return;          } @@ -173,15 +155,15 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val)  {      switch(key.as<dsp_prop_t>()) { +    // TODO: Set both codec frequencies until we have duality properties       case DSP_PROP_FREQ_SHIFT: {              double new_freq = val.as<double>();              _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); +            _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq);              _tx_dsp_freq = new_freq;              return;          } -    //TODO freq prop secondary: DBOARD_SLOT_B codec... -      case DSP_PROP_HOST_RATE: {              unsigned int rate =                      _clock_ctrl->get_master_clock_freq() * 2 / val.as<double>(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index ece5f1dea..ee6fe6e99 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -138,8 +138,12 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport,      _clock_ctrl = usrp1_clock_ctrl::make(_iface);      //create codec interface -    _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_A); -    _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_B); +    _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make( +        _iface, _clock_ctrl, SPI_ENABLE_CODEC_A +    ); +    _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make( +        _iface, _clock_ctrl, SPI_ENABLE_CODEC_B +    );      //initialize the codecs      codec_init(); | 
