diff options
| -rwxr-xr-x | host/lib/ic_reg_maps/gen_ad9862_regs.py | 2 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e/CMakeLists.txt | 28 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e/clock_ctrl.cpp | 1 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e/codec_ctrl.cpp | 145 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e/codec_ctrl.hpp | 10 | 
5 files changed, 141 insertions, 45 deletions
| diff --git a/host/lib/ic_reg_maps/gen_ad9862_regs.py b/host/lib/ic_reg_maps/gen_ad9862_regs.py index 2094f5e4b..4444c6240 100755 --- a/host/lib/ic_reg_maps/gen_ad9862_regs.py +++ b/host/lib/ic_reg_maps/gen_ad9862_regs.py @@ -233,7 +233,7 @@ boost::uint16_t get_write_reg(boost::uint8_t addr){  }  boost::uint16_t get_read_reg(boost::uint8_t addr){ -    return (boost::uint16_t(addr) << 8) | (1 << 7); +    return (boost::uint16_t(addr) << 8) | (1 << 15);  }  """ diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index 2eff3147d..c25b2cba4 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -17,18 +17,26 @@  #This file will be included by cmake, use absolute paths! +######################################################################## +# Helpful macro to check for required headers +######################################################################## +INCLUDE(CheckIncludeFileCXX) +SET(HAVE_USRP_E_REQUIRED_HEADERS TRUE) +MACRO(USRP_E_REQUIRE_HEADER header variable) +    CHECK_INCLUDE_FILE_CXX(${header} ${variable}) +    IF(NOT ${variable}) +        SET(HAVE_USRP_E_REQUIRED_HEADERS FALSE) +    ENDIF(NOT ${variable}) +ENDMACRO(USRP_E_REQUIRE_HEADER) + +######################################################################## +# Conditionally configure the USRP-E support +########################################################################  MESSAGE(STATUS "Configuring usrp-e support...") -INCLUDE(CheckIncludeFiles) -SET(usrp_e_required_headers -    linux/ioctl.h -    linux/spi/spidev.h -    linux/usrp_e.h -) -CHECK_INCLUDE_FILES( -    "${usrp_e_required_headers}" -    HAVE_USRP_E_REQUIRED_HEADERS -) +USRP_E_REQUIRE_HEADER(linux/ioctl.h      HAVE_LINUX_IOCTL_H) +USRP_E_REQUIRE_HEADER(linux/spi/spidev.h HAVE_LINUX_SPI_SPIDEV_H) +USRP_E_REQUIRE_HEADER(linux/usrp_e.h     HAVE_LINUX_USRP_E_H)  IF(HAVE_USRP_E_REQUIRED_HEADERS)      MESSAGE(STATUS "  Building usrp-e support.") diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 2fe3c9294..9c2ddf670 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -37,7 +37,6 @@ public:      void enable_rx_dboard_clock(bool enb);      void enable_tx_dboard_clock(bool enb); -    void enable_codec_clock(bool enb);  private:      usrp_e_iface::sptr _iface; diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index daa6ed3e3..a430f2c6f 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -17,34 +17,16 @@  #include "codec_ctrl.hpp"  #include "ad9862_regs.hpp" +#include <uhd/types/dict.hpp> +#include <uhd/utils/assert.hpp> +#include <uhd/utils/algorithm.hpp>  #include <boost/cstdint.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/math/special_functions/round.hpp>  #include "usrp_e_regs.hpp" //spi slave constants  #include <boost/assign/list_of.hpp> -//#include <boost/foreach.hpp> -//#include <utility>  #include <iostream> -    //test out codec ls dac/adc -    //ad9862_regs_t ad9862_regs; -    //ad9862_regs.select_a = ad9862_regs_t::SELECT_A_AUX_ADC1; -    //ad9862_regs.aux_dac_a = 0xff/2; -    //_iface->transact_spi( -    //    UE_SPI_SS_AD9862, -    //    spi_config_t::EDGE_RISE, -    //    ad9862_regs.get_write_reg(34), 16, false /*no rb*/ -    //); -    //_iface->transact_spi( -    //    UE_SPI_SS_AD9862, -    //    spi_config_t::EDGE_RISE, -    //    ad9862_regs.get_write_reg(36), 16, false /*no rb*/ -    //); -    //boost::uint32_t val = _iface->transact_spi( -    //    UE_SPI_SS_AD9862, -    //    spi_config_t::EDGE_RISE, -    //    ad9862_regs.get_read_reg(29), 16, true -    //); -    //std::cout << "value: " << std::hex << val << std::endl; -  using namespace uhd;  /*********************************************************************** @@ -58,16 +40,18 @@ public:      //aux adc and dac control      float read_aux_adc(aux_adc_t which); -    void read_aux_adc(aux_dac_t which, float volts); +    void write_aux_dac(aux_dac_t which, float volts);  private:      usrp_e_iface::sptr _iface;      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);  };  /*********************************************************************** - * Codec Control Methods + * Codec Control Structors   **********************************************************************/  codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){      _iface = iface; @@ -88,6 +72,13 @@ codec_ctrl_impl::codec_ctrl_impl(usrp_e_iface::sptr iface){  }  codec_ctrl_impl::~codec_ctrl_impl(void){ +    //set aux dacs to zero +    this->write_aux_dac(AUX_DAC_A, 0); +    this->write_aux_dac(AUX_DAC_B, 0); +    this->write_aux_dac(AUX_DAC_C, 0); +    this->write_aux_dac(AUX_DAC_D, 0); + +    //power down      _ad9862_regs.all_rx_pd = 1;      this->send_reg(1);      _ad9862_regs.tx_digital_pd = 1; @@ -95,23 +86,119 @@ codec_ctrl_impl::~codec_ctrl_impl(void){      this->send_reg(8);  } +/*********************************************************************** + * Codec Control AUX ADC Methods + **********************************************************************/ +static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low){ +    return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff; +} +  float codec_ctrl_impl::read_aux_adc(aux_adc_t which){ -    return 0; +    //check to see if the switch needs to be set +    bool write_switch = false; +    switch(which){ + +    case AUX_ADC_A1: +    case AUX_ADC_A2: +        if (which != _last_aux_adc_a){ +            _ad9862_regs.select_a = (which == AUX_ADC_A1)? +                ad9862_regs_t::SELECT_A_AUX_ADC1: ad9862_regs_t::SELECT_A_AUX_ADC2; +            _last_aux_adc_a = which; +            write_switch = true; +        } +        break; + +    case AUX_ADC_B1: +    case AUX_ADC_B2: +        if (which != _last_aux_adc_b){ +            _ad9862_regs.select_b = (which == AUX_ADC_B1)? +                ad9862_regs_t::SELECT_B_AUX_ADC1: ad9862_regs_t::SELECT_B_AUX_ADC2; +            _last_aux_adc_b = which; +            write_switch = true; +        } +        break; + +    } +    //write the switch if it changed +    if(write_switch) this->send_reg(34); + +    //map aux adcs to register values to read +    static const uhd::dict<aux_adc_t, boost::uint8_t> aux_dac_to_addr = boost::assign::map_list_of +        (AUX_ADC_A2, 26) (AUX_ADC_A1, 28) +        (AUX_ADC_B2, 30) (AUX_ADC_B1, 32) +    ; + +    //read the value +    this->recv_reg(aux_dac_to_addr[which]+0); +    this->recv_reg(aux_dac_to_addr[which]+1); + +    //return the value scaled to volts +    switch(which){ +    case AUX_ADC_A1: return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0); +    case AUX_ADC_A2: return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0); +    case AUX_ADC_B1: return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0); +    case AUX_ADC_B2: return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0); +    } +    UHD_ASSERT_THROW(false);  } -void codec_ctrl_impl::read_aux_adc(aux_dac_t which, float volts){ -     +/*********************************************************************** + * Codec Control AUX DAC Methods + **********************************************************************/ +void codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){ +    //special case for aux dac d (aka sigma delta word) +    if (which == AUX_DAC_D){ +        boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff); +        _ad9862_regs.sig_delt_11_4 = boost::uint8_t(dac_word >> 4); +        _ad9862_regs.sig_delt_3_0 = boost::uint8_t(dac_word & 0xf); +        this->send_reg(42); +        this->send_reg(43); +        return; +    } + +    //calculate the dac word for aux dac a, b, c +    boost::uint8_t dac_word = std::clip(boost::math::iround(volts*0xff/3.3), 0, 0xff); + +    //setup a lookup table for the aux dac params (reg ref, reg addr) +    typedef boost::tuple<boost::uint8_t*, boost::uint8_t> dac_params_t; +    uhd::dict<aux_dac_t, dac_params_t> aux_dac_to_params = boost::assign::map_list_of +        (AUX_DAC_A, dac_params_t(&_ad9862_regs.aux_dac_a, 36)) +        (AUX_DAC_B, dac_params_t(&_ad9862_regs.aux_dac_b, 37)) +        (AUX_DAC_C, dac_params_t(&_ad9862_regs.aux_dac_c, 38)) +    ; + +    //set the aux dac register +    UHD_ASSERT_THROW(aux_dac_to_params.has_key(which)); +    boost::uint8_t *reg_ref, reg_addr; +    boost::tie(reg_ref, reg_addr) = aux_dac_to_params[which]; +    *reg_ref = dac_word; +    this->send_reg(reg_addr);  } +/*********************************************************************** + * Codec Control SPI Methods + **********************************************************************/  void codec_ctrl_impl::send_reg(boost::uint8_t addr){      boost::uint32_t reg = _ad9862_regs.get_write_reg(addr);      //std::cout << "codec control write reg: " << std::hex << reg << std::endl;      _iface->transact_spi(          UE_SPI_SS_AD9862,          spi_config_t::EDGE_RISE, -        reg, 24, false /*no rb*/ +        reg, 16, false /*no rb*/ +    ); +} + +void codec_ctrl_impl::recv_reg(boost::uint8_t addr){ +    boost::uint32_t reg = _ad9862_regs.get_read_reg(addr); +    //std::cout << "codec control read reg: " << std::hex << reg << std::endl; +    boost::uint32_t ret = _iface->transact_spi( +        UE_SPI_SS_AD9862, +        spi_config_t::EDGE_RISE, +        reg, 16, true /*rb*/      ); +    //std::cout << "codec control read ret: " << std::hex << ret << std::endl; +    _ad9862_regs.set_reg(addr, boost::uint16_t(ret));  }  /*********************************************************************** diff --git a/host/lib/usrp/usrp_e/codec_ctrl.hpp b/host/lib/usrp/usrp_e/codec_ctrl.hpp index 0fe70c4a2..efdcd7142 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.hpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.hpp @@ -47,7 +47,9 @@ public:      };      /*! -     * Read the aux adc. +     * Read an auxiliary adc: +     * The internals remember which aux adc was read last. +     * Therefore, the aux adc switch is only changed as needed.       * \param which which of the 4 adcs       * \return a value in volts       */ @@ -58,15 +60,15 @@ public:          AUX_DAC_A = 0xA,          AUX_DAC_B = 0xB,          AUX_DAC_C = 0xC, -        AUX_DAC_D = 0xD +        AUX_DAC_D = 0xD //really the sigma delta output      };      /*! -     * Write the aux dac. +     * Write an auxiliary dac.       * \param which which of the 4 dacs       * \param volts the level in in volts       */ -    virtual void read_aux_adc(aux_dac_t which, float volts) = 0; +    virtual void write_aux_dac(aux_dac_t which, float volts) = 0;  }; | 
