diff options
-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(); |