Revision 9cb9e7d5
| b/host/lib/usrp/CMakeLists.txt | ||
|---|---|---|
| 32 | 32 |
) |
| 33 | 33 |
|
| 34 | 34 |
INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/dboard/CMakeLists.txt)
|
| 35 |
INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/CMakeLists.txt)
|
|
| 35 | 36 |
INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/CMakeLists.txt)
|
| b/host/lib/usrp/usrp1/CMakeLists.txt | ||
|---|---|---|
| 1 |
# |
|
| 2 |
# Copyright 2010 Ettus Research LLC |
|
| 3 |
# |
|
| 4 |
# This program is free software: you can redistribute it and/or modify |
|
| 5 |
# it under the terms of the GNU General Public License as published by |
|
| 6 |
# the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
# (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 16 |
# |
|
| 17 |
|
|
| 18 |
#This file will be included by cmake, use absolute paths! |
|
| 19 |
|
|
| 20 |
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/../firmware/fx2/include)
|
|
| 21 |
|
|
| 22 |
LIBUHD_APPEND_SOURCES( |
|
| 23 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/clock_ctrl.cpp
|
|
| 24 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/clock_ctrl.hpp
|
|
| 25 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_ctrl.cpp
|
|
| 26 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_ctrl.hpp
|
|
| 27 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_impl.cpp
|
|
| 28 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dboard_impl.cpp
|
|
| 29 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dboard_iface.cpp
|
|
| 30 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dsp_impl.cpp
|
|
| 31 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/io_impl.cpp
|
|
| 32 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/mboard_impl.cpp
|
|
| 33 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_iface.cpp
|
|
| 34 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_iface.hpp
|
|
| 35 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_impl.cpp
|
|
| 36 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_impl.hpp
|
|
| 37 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_ctrl.cpp
|
|
| 38 |
${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_ctrl.hpp
|
|
| 39 |
) |
|
| b/host/lib/usrp/usrp1/clock_ctrl.cpp | ||
|---|---|---|
| 1 |
// |
|
| 2 |
// Copyright 2010 Ettus Research LLC |
|
| 3 |
// |
|
| 4 |
// This program is free software: you can redistribute it and/or modify |
|
| 5 |
// it under the terms of the GNU General Public License as published by |
|
| 6 |
// the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
// (at your option) any later version. |
|
| 8 |
// |
|
| 9 |
// This program is distributed in the hope that it will be useful, |
|
| 10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
// GNU General Public License for more details. |
|
| 13 |
// |
|
| 14 |
// You should have received a copy of the GNU General Public License |
|
| 15 |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 16 |
// |
|
| 17 |
|
|
| 18 |
#include "clock_ctrl.hpp" |
|
| 19 |
#include "fpga_regs_standard.h" |
|
| 20 |
#include <uhd/utils/assert.hpp> |
|
| 21 |
#include <boost/cstdint.hpp> |
|
| 22 |
#include <boost/assign/list_of.hpp> |
|
| 23 |
#include <boost/foreach.hpp> |
|
| 24 |
#include <utility> |
|
| 25 |
#include <iostream> |
|
| 26 |
|
|
| 27 |
using namespace uhd; |
|
| 28 |
|
|
| 29 |
/*********************************************************************** |
|
| 30 |
* Constants |
|
| 31 |
**********************************************************************/ |
|
| 32 |
static const double master_clock_rate = 64e6; |
|
| 33 |
|
|
| 34 |
/*********************************************************************** |
|
| 35 |
* Clock Control Implementation |
|
| 36 |
**********************************************************************/ |
|
| 37 |
class usrp1_clock_ctrl_impl : public usrp1_clock_ctrl {
|
|
| 38 |
public: |
|
| 39 |
usrp1_clock_ctrl_impl(usrp1_iface::sptr iface) |
|
| 40 |
{
|
|
| 41 |
_iface = iface; |
|
| 42 |
} |
|
| 43 |
|
|
| 44 |
double get_master_clock_freq(void) |
|
| 45 |
{
|
|
| 46 |
return master_clock_rate; |
|
| 47 |
} |
|
| 48 |
|
|
| 49 |
/*********************************************************************** |
|
| 50 |
* RX Dboard Clock Control (output 9, divider 3) |
|
| 51 |
**********************************************************************/ |
|
| 52 |
void enable_rx_dboard_clock(bool) |
|
| 53 |
{
|
|
| 54 |
std::cerr << "USRP: enable_rx_dboard_clock() disabled" << std::endl; |
|
| 55 |
_iface->poke32(FR_RX_A_REFCLK, 0); |
|
| 56 |
_iface->poke32(FR_RX_B_REFCLK, 0); |
|
| 57 |
} |
|
| 58 |
|
|
| 59 |
std::vector<double> get_rx_dboard_clock_rates(void) |
|
| 60 |
{
|
|
| 61 |
#if 0 |
|
| 62 |
std::vector<double> rates; |
|
| 63 |
for (size_t div = 1; div <= 127; div++) |
|
| 64 |
rates.push_back(master_clock_rate / div); |
|
| 65 |
return rates; |
|
| 66 |
#else |
|
| 67 |
return std::vector<double>(1, 64e6); |
|
| 68 |
#endif |
|
| 69 |
} |
|
| 70 |
|
|
| 71 |
/* |
|
| 72 |
* Daughterboard reference clock register |
|
| 73 |
* |
|
| 74 |
* Bit 7 - 1 turns on refclk, 0 allows IO use |
|
| 75 |
* Bits 6:0 - Divider value |
|
| 76 |
*/ |
|
| 77 |
void set_rx_dboard_clock_rate(double) |
|
| 78 |
{
|
|
| 79 |
#if 0 |
|
| 80 |
assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate"); |
|
| 81 |
size_t divider = size_t(rate/master_clock_rate); |
|
| 82 |
_iface->poke32(FR_RX_A_REFCLK, (divider & 0x7f) | 0x80); |
|
| 83 |
#else |
|
| 84 |
std::cerr << "USRP: set_rx_dboard_clock_rate() disabled" << std::endl; |
|
| 85 |
_iface->poke32(FR_RX_A_REFCLK, 0); |
|
| 86 |
_iface->poke32(FR_RX_B_REFCLK, 0); |
|
| 87 |
#endif |
|
| 88 |
} |
|
| 89 |
|
|
| 90 |
/*********************************************************************** |
|
| 91 |
* TX Dboard Clock Control |
|
| 92 |
**********************************************************************/ |
|
| 93 |
void enable_tx_dboard_clock(bool) |
|
| 94 |
{
|
|
| 95 |
std::cerr << "USRP: set_tx_dboard_clock() disabled" << std::endl; |
|
| 96 |
_iface->poke32(FR_TX_A_REFCLK, 0); |
|
| 97 |
_iface->poke32(FR_TX_B_REFCLK, 0); |
|
| 98 |
|
|
| 99 |
} |
|
| 100 |
|
|
| 101 |
std::vector<double> get_tx_dboard_clock_rates(void) |
|
| 102 |
{
|
|
| 103 |
return get_rx_dboard_clock_rates(); //same master clock, same dividers... |
|
| 104 |
} |
|
| 105 |
|
|
| 106 |
void set_tx_dboard_clock_rate(double) |
|
| 107 |
{
|
|
| 108 |
std::cerr << "USRP: set_tx_dboard_clock_rate() disabled" << std::endl; |
|
| 109 |
_iface->poke32(FR_TX_A_REFCLK, 0); |
|
| 110 |
_iface->poke32(FR_TX_B_REFCLK, 0); |
|
| 111 |
} |
|
| 112 |
|
|
| 113 |
private: |
|
| 114 |
usrp1_iface::sptr _iface; |
|
| 115 |
|
|
| 116 |
}; |
|
| 117 |
|
|
| 118 |
/*********************************************************************** |
|
| 119 |
* Clock Control Make |
|
| 120 |
**********************************************************************/ |
|
| 121 |
usrp1_clock_ctrl::sptr usrp1_clock_ctrl::make(usrp1_iface::sptr iface) |
|
| 122 |
{
|
|
| 123 |
return sptr(new usrp1_clock_ctrl_impl(iface)); |
|
| 124 |
} |
|
| b/host/lib/usrp/usrp1/clock_ctrl.hpp | ||
|---|---|---|
| 1 |
// |
|
| 2 |
// Copyright 2010 Ettus Research LLC |
|
| 3 |
// |
|
| 4 |
// This program is free software: you can redistribute it and/or modify |
|
| 5 |
// it under the terms of the GNU General Public License as published by |
|
| 6 |
// the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
// (at your option) any later version. |
|
| 8 |
// |
|
| 9 |
// This program is distributed in the hope that it will be useful, |
|
| 10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
// GNU General Public License for more details. |
|
| 13 |
// |
|
| 14 |
// You should have received a copy of the GNU General Public License |
|
| 15 |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 16 |
// |
|
| 17 |
|
|
| 18 |
#ifndef INCLUDED_USRP1_CLOCK_CTRL_HPP |
|
| 19 |
#define INCLUDED_USRP1_CLOCK_CTRL_HPP |
|
| 20 |
|
|
| 21 |
#include "usrp1_iface.hpp" |
|
| 22 |
#include <boost/shared_ptr.hpp> |
|
| 23 |
#include <boost/utility.hpp> |
|
| 24 |
#include <vector> |
|
| 25 |
|
|
| 26 |
/*! |
|
| 27 |
* The usrp1 clock control: |
|
| 28 |
* - Setup system clocks. |
|
| 29 |
* - Disable/enable clock lines. |
|
| 30 |
*/ |
|
| 31 |
class usrp1_clock_ctrl : boost::noncopyable{
|
|
| 32 |
public: |
|
| 33 |
typedef boost::shared_ptr<usrp1_clock_ctrl> sptr; |
|
| 34 |
|
|
| 35 |
/*! |
|
| 36 |
* Make a new clock control object. |
|
| 37 |
* \param iface the usrp1 iface object |
|
| 38 |
* \return the clock control object |
|
| 39 |
*/ |
|
| 40 |
static sptr make(usrp1_iface::sptr iface); |
|
| 41 |
|
|
| 42 |
/*! |
|
| 43 |
* Get the rate of the fpga clock line. |
|
| 44 |
* \return the fpga clock rate in Hz |
|
| 45 |
*/ |
|
| 46 |
virtual double get_master_clock_freq(void) = 0; |
|
| 47 |
|
|
| 48 |
/*! |
|
| 49 |
* Get the possible rates of the rx dboard clock. |
|
| 50 |
* \return a vector of clock rates in Hz |
|
| 51 |
*/ |
|
| 52 |
virtual std::vector<double> get_rx_dboard_clock_rates(void) = 0; |
|
| 53 |
|
|
| 54 |
/*! |
|
| 55 |
* Get the possible rates of the tx dboard clock. |
|
| 56 |
* \return a vector of clock rates in Hz |
|
| 57 |
*/ |
|
| 58 |
virtual std::vector<double> get_tx_dboard_clock_rates(void) = 0; |
|
| 59 |
|
|
| 60 |
/*! |
|
| 61 |
* Set the rx dboard clock rate to a possible rate. |
|
| 62 |
* \param rate the new clock rate in Hz |
|
| 63 |
* \throw exception when rate cannot be achieved |
|
| 64 |
*/ |
|
| 65 |
virtual void set_rx_dboard_clock_rate(double rate) = 0; |
|
| 66 |
|
|
| 67 |
/*! |
|
| 68 |
* Set the tx dboard clock rate to a possible rate. |
|
| 69 |
* \param rate the new clock rate in Hz |
|
| 70 |
* \throw exception when rate cannot be achieved |
|
| 71 |
*/ |
|
| 72 |
virtual void set_tx_dboard_clock_rate(double rate) = 0; |
|
| 73 |
|
|
| 74 |
/*! |
|
| 75 |
* Enable/disable the rx dboard clock. |
|
| 76 |
* \param enb true to enable |
|
| 77 |
*/ |
|
| 78 |
virtual void enable_rx_dboard_clock(bool enb) = 0; |
|
| 79 |
|
|
| 80 |
/*! |
|
| 81 |
* Enable/disable the tx dboard clock. |
|
| 82 |
* \param enb true to enable |
|
| 83 |
*/ |
|
| 84 |
virtual void enable_tx_dboard_clock(bool enb) = 0; |
|
| 85 |
|
|
| 86 |
}; |
|
| 87 |
|
|
| 88 |
#endif /* INCLUDED_USRP1_CLOCK_CTRL_HPP */ |
|
| b/host/lib/usrp/usrp1/codec_ctrl.cpp | ||
|---|---|---|
| 1 |
// |
|
| 2 |
// Copyright 2010 Ettus Research LLC |
|
| 3 |
// |
|
| 4 |
// This program is free software: you can redistribute it and/or modify |
|
| 5 |
// it under the terms of the GNU General Public License as published by |
|
| 6 |
// the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
// (at your option) any later version. |
|
| 8 |
// |
|
| 9 |
// This program is distributed in the hope that it will be useful, |
|
| 10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
// GNU General Public License for more details. |
|
| 13 |
// |
|
| 14 |
// You should have received a copy of the GNU General Public License |
|
| 15 |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 16 |
// |
|
| 17 |
|
|
| 18 |
#include "codec_ctrl.hpp" |
|
| 19 |
#include "usrp_commands.h" |
|
| 20 |
#include "fpga_regs_standard.h" |
|
| 21 |
#include "usrp_spi_defs.h" |
|
| 22 |
#include "ad9862_regs.hpp" |
|
| 23 |
#include <uhd/types/dict.hpp> |
|
| 24 |
#include <uhd/utils/assert.hpp> |
|
| 25 |
#include <uhd/utils/algorithm.hpp> |
|
| 26 |
#include <uhd/utils/byteswap.hpp> |
|
| 27 |
#include <boost/cstdint.hpp> |
|
| 28 |
#include <boost/tuple/tuple.hpp> |
|
| 29 |
#include <boost/math/special_functions/round.hpp> |
|
| 30 |
#include <boost/assign/list_of.hpp> |
|
| 31 |
#include <iostream> |
|
| 32 |
#include <iomanip> |
|
| 33 |
#include <cstdio> |
|
| 34 |
|
|
| 35 |
using namespace uhd; |
|
| 36 |
|
|
| 37 |
static const bool codec_debug = true; |
|
| 38 |
|
|
| 39 |
const gain_range_t usrp1_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1)); |
|
| 40 |
const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1); |
|
| 41 |
|
|
| 42 |
/*********************************************************************** |
|
| 43 |
* Codec Control Implementation |
|
| 44 |
**********************************************************************/ |
|
| 45 |
class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl {
|
|
| 46 |
public: |
|
| 47 |
//structors |
|
| 48 |
usrp1_codec_ctrl_impl(usrp1_iface::sptr iface); |
|
| 49 |
~usrp1_codec_ctrl_impl(void); |
|
| 50 |
|
|
| 51 |
//aux adc and dac control |
|
| 52 |
float read_aux_adc(aux_adc_t which); |
|
| 53 |
void write_aux_dac(aux_dac_t which, float volts); |
|
| 54 |
|
|
| 55 |
//duc control |
|
| 56 |
bool set_duc_freq(double freq); |
|
| 57 |
|
|
| 58 |
//pga gain control |
|
| 59 |
void set_tx_pga_gain(float); |
|
| 60 |
float get_tx_pga_gain(void); |
|
| 61 |
void set_rx_pga_gain(float, char); |
|
| 62 |
float get_rx_pga_gain(char); |
|
| 63 |
|
|
| 64 |
private: |
|
| 65 |
usrp1_iface::sptr _iface; |
|
| 66 |
ad9862_regs_t _ad9862_regs; |
|
| 67 |
aux_adc_t _last_aux_adc_a, _last_aux_adc_b; |
|
| 68 |
void send_reg(boost::uint8_t addr); |
|
| 69 |
void recv_reg(boost::uint8_t addr); |
|
| 70 |
|
|
| 71 |
//FIXME: poison |
|
| 72 |
double _tx_freq[4]; |
|
| 73 |
unsigned int compute_freq_control_word_9862 (double master_freq, |
|
| 74 |
double target_freq, |
|
| 75 |
double *actual_freq); |
|
| 76 |
}; |
|
| 77 |
|
|
| 78 |
/*********************************************************************** |
|
| 79 |
* Codec Control Structors |
|
| 80 |
**********************************************************************/ |
|
| 81 |
usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface) |
|
| 82 |
{
|
|
| 83 |
_iface = iface; |
|
| 84 |
|
|
| 85 |
//soft reset |
|
| 86 |
_ad9862_regs.soft_reset = 1; |
|
| 87 |
this->send_reg(0); |
|
| 88 |
|
|
| 89 |
//initialize the codec register settings |
|
| 90 |
_ad9862_regs.sdio_bidir = ad9862_regs_t::SDIO_BIDIR_SDIO_SDO; |
|
| 91 |
_ad9862_regs.lsb_first = ad9862_regs_t::LSB_FIRST_MSB; |
|
| 92 |
_ad9862_regs.soft_reset = 0; |
|
| 93 |
|
|
| 94 |
//setup rx side of codec |
|
| 95 |
_ad9862_regs.byp_buffer_a = 1; |
|
| 96 |
_ad9862_regs.byp_buffer_b = 1; |
|
| 97 |
_ad9862_regs.buffer_a_pd = 1; |
|
| 98 |
_ad9862_regs.buffer_b_pd = 1; |
|
| 99 |
_ad9862_regs.rx_pga_a = 0;//0x1f; //TODO bring under api control |
|
| 100 |
_ad9862_regs.rx_pga_b = 0;//0x1f; //TODO bring under api control |
|
| 101 |
_ad9862_regs.rx_twos_comp = 1; |
|
| 102 |
_ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS; |
|
| 103 |
|
|
| 104 |
//setup tx side of codec |
|
| 105 |
_ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH; |
|
| 106 |
_ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED; |
|
| 107 |
_ad9862_regs.tx_pga_gain = 199; //TODO bring under api control |
|
| 108 |
_ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS; |
|
| 109 |
_ad9862_regs.interp = ad9862_regs_t::INTERP_4; |
|
| 110 |
_ad9862_regs.tx_twos_comp = 1; |
|
| 111 |
_ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; |
|
| 112 |
_ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; |
|
| 113 |
_ad9862_regs.dac_a_coarse_gain = 0x3; |
|
| 114 |
_ad9862_regs.dac_b_coarse_gain = 0x3; |
|
| 115 |
|
|
| 116 |
//setup the dll |
|
| 117 |
_ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL; |
|
| 118 |
_ad9862_regs.dll_mult = ad9862_regs_t::DLL_MULT_2; |
|
| 119 |
_ad9862_regs.dll_mode = ad9862_regs_t::DLL_MODE_FAST; |
|
| 120 |
|
|
| 121 |
//setup clockout |
|
| 122 |
_ad9862_regs.clkout2_div_factor = ad9862_regs_t::CLKOUT2_DIV_FACTOR_2; |
|
| 123 |
|
|
| 124 |
//write the register settings to the codec |
|
| 125 |
for (uint8_t addr = 0; addr <= 25; addr++) {
|
|
| 126 |
this->send_reg(addr); |
|
| 127 |
} |
|
| 128 |
|
|
| 129 |
//aux adc clock |
|
| 130 |
_ad9862_regs.clk_4 = ad9862_regs_t::CLK_4_1_4; |
|
| 131 |
this->send_reg(34); |
|
| 132 |
} |
|
| 133 |
|
|
| 134 |
usrp1_codec_ctrl_impl::~usrp1_codec_ctrl_impl(void) |
|
| 135 |
{
|
|
| 136 |
//set aux dacs to zero |
|
| 137 |
this->write_aux_dac(AUX_DAC_A, 0); |
|
| 138 |
this->write_aux_dac(AUX_DAC_B, 0); |
|
| 139 |
this->write_aux_dac(AUX_DAC_C, 0); |
|
| 140 |
this->write_aux_dac(AUX_DAC_D, 0); |
|
| 141 |
|
|
| 142 |
//power down |
|
| 143 |
_ad9862_regs.all_rx_pd = 1; |
|
| 144 |
this->send_reg(1); |
|
| 145 |
_ad9862_regs.tx_digital_pd = 1; |
|
| 146 |
_ad9862_regs.tx_analog_pd = ad9862_regs_t::TX_ANALOG_PD_BOTH; |
|
| 147 |
this->send_reg(8); |
|
| 148 |
} |
|
| 149 |
|
|
| 150 |
/*********************************************************************** |
|
| 151 |
* Codec Control Gain Control Methods |
|
| 152 |
**********************************************************************/ |
|
| 153 |
void usrp1_codec_ctrl_impl::set_tx_pga_gain(float gain) |
|
| 154 |
{
|
|
| 155 |
int gain_word = int(63*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); |
|
| 156 |
_ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 63); |
|
| 157 |
this->send_reg(16); |
|
| 158 |
} |
|
| 159 |
|
|
| 160 |
float usrp1_codec_ctrl_impl::get_tx_pga_gain(void) |
|
| 161 |
{
|
|
| 162 |
return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/63) + tx_pga_gain_range.min; |
|
| 163 |
} |
|
| 164 |
|
|
| 165 |
void usrp1_codec_ctrl_impl::set_rx_pga_gain(float gain, char which) |
|
| 166 |
{
|
|
| 167 |
int gain_word = int(0x14*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min)); |
|
| 168 |
gain_word = std::clip(gain_word, 0, 0x14); |
|
| 169 |
switch(which){
|
|
| 170 |
case 'A': |
|
| 171 |
_ad9862_regs.rx_pga_a = gain_word; |
|
| 172 |
this->send_reg(2); |
|
| 173 |
return; |
|
| 174 |
case 'B': |
|
| 175 |
_ad9862_regs.rx_pga_b = gain_word; |
|
| 176 |
this->send_reg(3); |
|
| 177 |
return; |
|
| 178 |
default: UHD_THROW_INVALID_CODE_PATH(); |
|
| 179 |
} |
|
| 180 |
} |
|
| 181 |
|
|
| 182 |
float usrp1_codec_ctrl_impl::get_rx_pga_gain(char which) |
|
| 183 |
{
|
|
| 184 |
int gain_word; |
|
| 185 |
switch(which){
|
|
| 186 |
case 'A': gain_word = _ad9862_regs.rx_pga_a; break; |
|
| 187 |
case 'B': gain_word = _ad9862_regs.rx_pga_b; break; |
|
| 188 |
default: UHD_THROW_INVALID_CODE_PATH(); |
|
| 189 |
} |
|
| 190 |
return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/0x14) + rx_pga_gain_range.min; |
|
| 191 |
} |
|
| 192 |
|
|
| 193 |
/*********************************************************************** |
|
| 194 |
* Codec Control AUX ADC Methods |
|
| 195 |
**********************************************************************/ |
|
| 196 |
static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low) |
|
| 197 |
{
|
|
| 198 |
return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff; |
|
| 199 |
} |
|
| 200 |
|
|
| 201 |
float usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which) |
|
| 202 |
{
|
|
| 203 |
//check to see if the switch needs to be set |
|
| 204 |
bool write_switch = false; |
|
| 205 |
switch(which) {
|
|
| 206 |
|
|
| 207 |
case AUX_ADC_A1: |
|
| 208 |
case AUX_ADC_A2: |
|
| 209 |
if (which != _last_aux_adc_a) {
|
|
| 210 |
_ad9862_regs.select_a = (which == AUX_ADC_A1)? |
|
| 211 |
ad9862_regs_t::SELECT_A_AUX_ADC1: ad9862_regs_t::SELECT_A_AUX_ADC2; |
|
| 212 |
_last_aux_adc_a = which; |
|
| 213 |
write_switch = true; |
|
| 214 |
} |
|
| 215 |
break; |
|
| 216 |
|
|
| 217 |
case AUX_ADC_B1: |
|
| 218 |
case AUX_ADC_B2: |
|
| 219 |
if (which != _last_aux_adc_b) {
|
|
| 220 |
_ad9862_regs.select_b = (which == AUX_ADC_B1)? |
|
| 221 |
ad9862_regs_t::SELECT_B_AUX_ADC1: ad9862_regs_t::SELECT_B_AUX_ADC2; |
|
| 222 |
_last_aux_adc_b = which; |
|
| 223 |
write_switch = true; |
|
| 224 |
} |
|
| 225 |
break; |
|
| 226 |
|
|
| 227 |
} |
|
| 228 |
|
|
| 229 |
//write the switch if it changed |
|
| 230 |
if(write_switch) this->send_reg(34); |
|
| 231 |
|
|
| 232 |
//map aux adcs to register values to read |
|
| 233 |
static const uhd::dict<aux_adc_t, boost::uint8_t> aux_dac_to_addr = boost::assign::map_list_of |
|
| 234 |
(AUX_ADC_A2, 26) (AUX_ADC_A1, 28) |
|
| 235 |
(AUX_ADC_B2, 30) (AUX_ADC_B1, 32) |
|
| 236 |
; |
|
| 237 |
|
|
| 238 |
//read the value |
|
| 239 |
this->recv_reg(aux_dac_to_addr[which]+0); |
|
| 240 |
this->recv_reg(aux_dac_to_addr[which]+1); |
|
| 241 |
|
|
| 242 |
//return the value scaled to volts |
|
| 243 |
switch(which) {
|
|
| 244 |
case AUX_ADC_A1: return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0); |
|
| 245 |
case AUX_ADC_A2: return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0); |
|
| 246 |
case AUX_ADC_B1: return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0); |
|
| 247 |
case AUX_ADC_B2: return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0); |
|
| 248 |
} |
|
| 249 |
UHD_ASSERT_THROW(false); |
|
| 250 |
} |
|
| 251 |
|
|
| 252 |
/*********************************************************************** |
|
| 253 |
* Codec Control AUX DAC Methods |
|
| 254 |
**********************************************************************/ |
|
| 255 |
void usrp1_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts) |
|
| 256 |
{
|
|
| 257 |
//special case for aux dac d (aka sigma delta word) |
|
| 258 |
if (which == AUX_DAC_D) {
|
|
| 259 |
boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff); |
|
| 260 |
_ad9862_regs.sig_delt_11_4 = boost::uint8_t(dac_word >> 4); |
|
| 261 |
_ad9862_regs.sig_delt_3_0 = boost::uint8_t(dac_word & 0xf); |
|
| 262 |
this->send_reg(42); |
|
| 263 |
this->send_reg(43); |
|
| 264 |
return; |
|
| 265 |
} |
|
| 266 |
|
|
| 267 |
//calculate the dac word for aux dac a, b, c |
|
| 268 |
boost::uint8_t dac_word = std::clip(boost::math::iround(volts*0xff/3.3), 0, 0xff); |
|
| 269 |
|
|
| 270 |
//setup a lookup table for the aux dac params (reg ref, reg addr) |
|
| 271 |
typedef boost::tuple<boost::uint8_t*, boost::uint8_t> dac_params_t; |
|
| 272 |
uhd::dict<aux_dac_t, dac_params_t> aux_dac_to_params = boost::assign::map_list_of |
|
| 273 |
(AUX_DAC_A, dac_params_t(&_ad9862_regs.aux_dac_a, 36)) |
|
| 274 |
(AUX_DAC_B, dac_params_t(&_ad9862_regs.aux_dac_b, 37)) |
|
| 275 |
(AUX_DAC_C, dac_params_t(&_ad9862_regs.aux_dac_c, 38)) |
|
| 276 |
; |
|
| 277 |
|
|
| 278 |
//set the aux dac register |
|
| 279 |
UHD_ASSERT_THROW(aux_dac_to_params.has_key(which)); |
|
| 280 |
boost::uint8_t *reg_ref, reg_addr; |
|
| 281 |
boost::tie(reg_ref, reg_addr) = aux_dac_to_params[which]; |
|
| 282 |
*reg_ref = dac_word; |
|
| 283 |
this->send_reg(reg_addr); |
|
| 284 |
} |
|
| 285 |
|
|
| 286 |
/*********************************************************************** |
|
| 287 |
* Codec Control SPI Methods |
|
| 288 |
**********************************************************************/ |
|
| 289 |
void usrp1_codec_ctrl_impl::send_reg(boost::uint8_t addr) |
|
| 290 |
{
|
|
| 291 |
boost::uint32_t reg = _ad9862_regs.get_write_reg(addr); |
|
| 292 |
|
|
| 293 |
if (codec_debug) {
|
|
| 294 |
std::cout.fill('0');
|
|
| 295 |
std::cout << "codec control write reg: 0x"; |
|
| 296 |
std::cout << std::setw(8) << std::hex << reg << std::endl; |
|
| 297 |
} |
|
| 298 |
_iface->transact_spi(SPI_ENABLE_CODEC_A, |
|
| 299 |
spi_config_t::EDGE_RISE, reg, 16, false); |
|
| 300 |
} |
|
| 301 |
|
|
| 302 |
void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr) |
|
| 303 |
{
|
|
| 304 |
boost::uint32_t reg = _ad9862_regs.get_read_reg(addr); |
|
| 305 |
|
|
| 306 |
if (codec_debug) {
|
|
| 307 |
std::cout.fill('0');
|
|
| 308 |
std::cout << "codec control read reg: 0x"; |
|
| 309 |
std::cout << std::setw(8) << std::hex << reg << std::endl; |
|
| 310 |
} |
|
| 311 |
|
|
| 312 |
boost::uint32_t ret = _iface->transact_spi(SPI_ENABLE_CODEC_A, |
|
| 313 |
spi_config_t::EDGE_RISE, reg, 16, true); |
|
| 314 |
|
|
| 315 |
if (codec_debug) {
|
|
| 316 |
std::cout.fill('0');
|
|
| 317 |
std::cout << "codec control read ret: 0x"; |
|
| 318 |
std::cout << std::setw(8) << std::hex << ret << std::endl; |
|
| 319 |
} |
|
| 320 |
|
|
| 321 |
_ad9862_regs.set_reg(addr, boost::uint16_t(ret)); |
|
| 322 |
} |
|
| 323 |
|
|
| 324 |
/*********************************************************************** |
|
| 325 |
* DUC tuning |
|
| 326 |
**********************************************************************/ |
|
| 327 |
unsigned int usrp1_codec_ctrl_impl::compute_freq_control_word_9862( |
|
| 328 |
double master_freq, double target_freq, double *actual_freq) |
|
| 329 |
{
|
|
| 330 |
double sign = 1.0; |
|
| 331 |
|
|
| 332 |
if (target_freq < 0) |
|
| 333 |
sign = -1.0; |
|
| 334 |
|
|
| 335 |
int v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0)); |
|
| 336 |
*actual_freq = v * master_freq / pow (2.0, 24.0) * sign; |
|
| 337 |
|
|
| 338 |
fprintf(stdout, |
|
| 339 |
"compute_freq_control_word_9862: target = %g actual = %g delta = %g v = %8d\n", |
|
| 340 |
target_freq, *actual_freq, *actual_freq - target_freq, v); |
|
| 341 |
|
|
| 342 |
return (unsigned int) v; |
|
| 343 |
} |
|
| 344 |
|
|
| 345 |
bool usrp1_codec_ctrl_impl::set_duc_freq(double freq) |
|
| 346 |
{
|
|
| 347 |
int channel = 0; |
|
| 348 |
float dac_rate = 128e6; |
|
| 349 |
|
|
| 350 |
double coarse; |
|
| 351 |
|
|
| 352 |
std::cout << "duc_freq: " << freq << std::endl; |
|
| 353 |
|
|
| 354 |
// First coarse frequency |
|
| 355 |
double coarse_freq_1 = dac_rate / 8; |
|
| 356 |
// Second coarse frequency |
|
| 357 |
double coarse_freq_2 = dac_rate / 4; |
|
| 358 |
// Midpoint of [0 , freq1] range |
|
| 359 |
double coarse_limit_1 = coarse_freq_1 / 2; |
|
| 360 |
// Midpoint of [freq1 , freq2] range |
|
| 361 |
double coarse_limit_2 = (coarse_freq_1 + coarse_freq_2) / 2; |
|
| 362 |
// Highest meaningful frequency |
|
| 363 |
double high_limit = (double) 44e6 / 128e6 * dac_rate; |
|
| 364 |
|
|
| 365 |
if (freq < -high_limit) { // too low
|
|
| 366 |
return false; |
|
| 367 |
} |
|
| 368 |
else if (freq < -coarse_limit_2) { // For 64MHz: [-44, -24)
|
|
| 369 |
_ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT; |
|
| 370 |
_ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; |
|
| 371 |
coarse = -coarse_freq_2; |
|
| 372 |
} |
|
| 373 |
else if (freq < -coarse_limit_1) { // For 64MHz: [-24, -8)
|
|
| 374 |
_ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT; |
|
| 375 |
_ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; |
|
| 376 |
coarse = -coarse_freq_1; |
|
| 377 |
} |
|
| 378 |
else if (freq < coarse_limit_1) { // For 64MHz: [-8, 8)
|
|
| 379 |
_ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; |
|
| 380 |
coarse = 0; |
|
| 381 |
} |
|
| 382 |
else if (freq < coarse_limit_2) { // For 64MHz: [8, 24)
|
|
| 383 |
_ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT; |
|
| 384 |
_ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; |
|
| 385 |
coarse = coarse_freq_1; |
|
| 386 |
} |
|
| 387 |
else if (freq <= high_limit) { // For 64MHz: [24, 44]
|
|
| 388 |
_ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT; |
|
| 389 |
_ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; |
|
| 390 |
coarse = coarse_freq_2; |
|
| 391 |
} |
|
| 392 |
else { // too high
|
|
| 393 |
return false; |
|
| 394 |
} |
|
| 395 |
|
|
| 396 |
double fine = freq - coarse; |
|
| 397 |
|
|
| 398 |
// Compute fine tuning word... |
|
| 399 |
// This assumes we're running the 4x on-chip interpolator. |
|
| 400 |
// (This is required to use the fine modulator.) |
|
| 401 |
|
|
| 402 |
unsigned int v = compute_freq_control_word_9862 (dac_rate / 4, fine, |
|
| 403 |
&_tx_freq[channel]); |
|
| 404 |
|
|
| 405 |
_tx_freq[channel] += coarse; // adjust actual |
|
| 406 |
|
|
| 407 |
boost::uint8_t high; |
|
| 408 |
boost::uint8_t mid; |
|
| 409 |
boost::uint8_t low; |
|
| 410 |
|
|
| 411 |
high = (v >> 16) & 0xff; |
|
| 412 |
mid = (v >> 8) & 0xff; |
|
| 413 |
low = (v >> 0) & 0xff; |
|
| 414 |
|
|
| 415 |
// write the fine tuning word |
|
| 416 |
_ad9862_regs.ftw_23_16 = high; |
|
| 417 |
_ad9862_regs.ftw_15_8 = mid; |
|
| 418 |
_ad9862_regs.ftw_7_0 = low; |
|
| 419 |
|
|
| 420 |
_ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; |
|
| 421 |
|
|
| 422 |
if (fine < 0) |
|
| 423 |
_ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_NEG_SHIFT; |
|
| 424 |
else |
|
| 425 |
_ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_POS_SHIFT; |
|
| 426 |
|
|
| 427 |
this->send_reg(20); |
|
| 428 |
this->send_reg(21); |
|
| 429 |
this->send_reg(22); |
|
| 430 |
this->send_reg(23); |
|
| 431 |
|
|
| 432 |
return true; |
|
| 433 |
} |
|
| 434 |
|
|
| 435 |
/*********************************************************************** |
|
| 436 |
* Codec Control Make |
|
| 437 |
**********************************************************************/ |
|
| 438 |
usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface) |
|
| 439 |
{
|
|
| 440 |
return sptr(new usrp1_codec_ctrl_impl(iface)); |
|
| 441 |
} |
|
| b/host/lib/usrp/usrp1/codec_ctrl.hpp | ||
|---|---|---|
| 1 |
// |
|
| 2 |
// Copyright 2010 Ettus Research LLC |
|
| 3 |
// |
|
| 4 |
// This program is free software: you can redistribute it and/or modify |
|
| 5 |
// it under the terms of the GNU General Public License as published by |
|
| 6 |
// the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
// (at your option) any later version. |
|
| 8 |
// |
|
| 9 |
// This program is distributed in the hope that it will be useful, |
|
| 10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
// GNU General Public License for more details. |
|
| 13 |
// |
|
| 14 |
// You should have received a copy of the GNU General Public License |
|
| 15 |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 16 |
// |
|
| 17 |
|
|
| 18 |
#ifndef INCLUDED_USRP1_CODEC_CTRL_HPP |
|
| 19 |
#define INCLUDED_USRP1_CODEC_CTRL_HPP |
|
| 20 |
|
|
| 21 |
#include "usrp1_iface.hpp" |
|
| 22 |
#include <boost/shared_ptr.hpp> |
|
| 23 |
#include <boost/utility.hpp> |
|
| 24 |
|
|
| 25 |
/*! |
|
| 26 |
* The usrp1 codec control: |
|
| 27 |
* - Init/power down codec. |
|
| 28 |
* - Read aux adc, write aux dac. |
|
| 29 |
*/ |
|
| 30 |
class usrp1_codec_ctrl : boost::noncopyable{
|
|
| 31 |
public: |
|
| 32 |
typedef boost::shared_ptr<usrp1_codec_ctrl> sptr; |
|
| 33 |
|
|
| 34 |
/*! |
|
| 35 |
* Make a new clock control object. |
|
| 36 |
* \param iface the usrp1 iface object |
|
| 37 |
* \return the clock control object |
|
| 38 |
*/ |
|
| 39 |
static sptr make(usrp1_iface::sptr iface); |
|
| 40 |
|
|
| 41 |
//! aux adc identifier constants |
|
| 42 |
enum aux_adc_t{
|
|
| 43 |
AUX_ADC_A2 = 0xA2, |
|
| 44 |
AUX_ADC_A1 = 0xA1, |
|
| 45 |
AUX_ADC_B2 = 0xB2, |
|
| 46 |
AUX_ADC_B1 = 0xB1 |
|
| 47 |
}; |
|
| 48 |
|
|
| 49 |
/*! |
|
| 50 |
* Read an auxiliary adc: |
|
| 51 |
* The internals remember which aux adc was read last. |
|
| 52 |
* Therefore, the aux adc switch is only changed as needed. |
|
| 53 |
* \param which which of the 4 adcs |
|
| 54 |
* \return a value in volts |
|
| 55 |
*/ |
|
| 56 |
virtual float read_aux_adc(aux_adc_t which) = 0; |
|
| 57 |
|
|
| 58 |
//! aux dac identifier constants |
|
| 59 |
enum aux_dac_t{
|
|
| 60 |
AUX_DAC_A = 0xA, |
|
| 61 |
AUX_DAC_B = 0xB, |
|
| 62 |
AUX_DAC_C = 0xC, |
|
| 63 |
AUX_DAC_D = 0xD |
|
| 64 |
}; |
|
| 65 |
|
|
| 66 |
/*! |
|
| 67 |
* Write an auxiliary dac. |
|
| 68 |
* \param which which of the 4 dacs |
|
| 69 |
* \param volts the level in in volts |
|
| 70 |
*/ |
|
| 71 |
virtual void write_aux_dac(aux_dac_t which, float volts) = 0; |
|
| 72 |
|
|
| 73 |
virtual bool set_duc_freq(double freq) = 0; |
|
| 74 |
}; |
|
| 75 |
|
|
| 76 |
#endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */ |
|
| b/host/lib/usrp/usrp1/codec_impl.cpp | ||
|---|---|---|
| 1 |
// |
|
| 2 |
// Copyright 2010 Ettus Research LLC |
|
| 3 |
// |
|
| 4 |
// This program is free software: you can redistribute it and/or modify |
|
| 5 |
// it under the terms of the GNU General Public License as published by |
|
| 6 |
// the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
// (at your option) any later version. |
|
| 8 |
// |
|
| 9 |
// This program is distributed in the hope that it will be useful, |
|
| 10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
// GNU General Public License for more details. |
|
| 13 |
// |
|
| 14 |
// You should have received a copy of the GNU General Public License |
|
| 15 |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 16 |
// |
|
| 17 |
|
|
| 18 |
#include "usrp1_impl.hpp" |
|
| 19 |
#include <uhd/usrp/codec_props.hpp> |
|
| 20 |
#include <boost/bind.hpp> |
|
| 21 |
|
|
| 22 |
using namespace uhd; |
|
| 23 |
using namespace uhd::usrp; |
|
| 24 |
|
|
| 25 |
/*********************************************************************** |
|
| 26 |
* Helper Methods |
|
| 27 |
**********************************************************************/ |
|
| 28 |
void usrp1_impl::codec_init(void) |
|
| 29 |
{
|
|
| 30 |
//make proxies |
|
| 31 |
_rx_codec_proxy = wax_obj_proxy::make( |
|
| 32 |
boost::bind(&usrp1_impl::rx_codec_get, this, _1, _2), |
|
| 33 |
boost::bind(&usrp1_impl::rx_codec_set, this, _1, _2)); |
|
| 34 |
|
|
| 35 |
_tx_codec_proxy = wax_obj_proxy::make( |
|
| 36 |
boost::bind(&usrp1_impl::tx_codec_get, this, _1, _2), |
|
| 37 |
boost::bind(&usrp1_impl::tx_codec_set, this, _1, _2)); |
|
| 38 |
} |
|
| 39 |
|
|
| 40 |
/*********************************************************************** |
|
| 41 |
* RX Codec Properties |
|
| 42 |
**********************************************************************/ |
|
| 43 |
static const std::string ad9862_pga_gain_name = "ad9862 pga"; |
|
| 44 |
|
|
| 45 |
void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val) |
|
| 46 |
{
|
|
| 47 |
wax::obj key; std::string name; |
|
| 48 |
boost::tie(key, name) = extract_named_prop(key_); |
|
| 49 |
|
|
| 50 |
//handle the get request conditioned on the key |
|
| 51 |
switch(key.as<codec_prop_t>()) {
|
|
| 52 |
case CODEC_PROP_NAME: |
|
| 53 |
val = std::string("usrp1 adc - ad9862");
|
|
| 54 |
return; |
|
| 55 |
|
|
| 56 |
case CODEC_PROP_OTHERS: |
|
| 57 |
val = prop_names_t(); |
|
| 58 |
return; |
|
| 59 |
|
|
| 60 |
case CODEC_PROP_GAIN_NAMES: |
|
| 61 |
val = prop_names_t(1, ad9862_pga_gain_name); |
|
| 62 |
return; |
|
| 63 |
|
|
| 64 |
case CODEC_PROP_GAIN_RANGE: |
|
| 65 |
UHD_ASSERT_THROW(name == ad9862_pga_gain_name); |
|
| 66 |
val = usrp1_codec_ctrl::rx_pga_gain_range; |
|
| 67 |
return; |
|
| 68 |
|
|
| 69 |
case CODEC_PROP_GAIN_I: |
|
| 70 |
UHD_ASSERT_THROW(name == ad9862_pga_gain_name); |
|
| 71 |
val = _codec_ctrl->get_rx_pga_gain('A');
|
|
| 72 |
return; |
|
| 73 |
|
|
| 74 |
case CODEC_PROP_GAIN_Q: |
|
| 75 |
UHD_ASSERT_THROW(name == ad9862_pga_gain_name); |
|
| 76 |
val = _codec_ctrl->get_rx_pga_gain('B');
|
|
| 77 |
return; |
|
| 78 |
|
|
| 79 |
default: UHD_THROW_PROP_GET_ERROR(); |
|
| 80 |
} |
|
| 81 |
} |
|
| 82 |
|
|
| 83 |
void usrp1_impl::rx_codec_set(const wax::obj &, const wax::obj &) |
|
| 84 |
{
|
|
| 85 |
wax::obj key; std::string name; |
|
| 86 |
boost::tie(key, name) = extract_named_prop(key_); |
|
| 87 |
|
|
| 88 |
//handle the set request conditioned on the key |
|
| 89 |
switch(key.as<codec_prop_t>()) {
|
|
| 90 |
case CODEC_PROP_GAIN_I: |
|
| 91 |
UHD_ASSERT_THROW(name == ad9862_pga_gain_name); |
|
| 92 |
_codec_ctrl->set_rx_pga_gain(val.as<float>(), 'A'); |
|
| 93 |
return; |
|
| 94 |
|
|
| 95 |
case CODEC_PROP_GAIN_Q: |
|
| 96 |
UHD_ASSERT_THROW(name == ad9862_pga_gain_name); |
|
| 97 |
_codec_ctrl->set_rx_pga_gain(val.as<float>(), 'B'); |
|
| 98 |
return; |
|
| 99 |
|
|
| 100 |
default: UHD_THROW_PROP_SET_ERROR(); |
|
| 101 |
} |
|
| 102 |
} |
|
| 103 |
|
|
| 104 |
/*********************************************************************** |
|
| 105 |
* TX Codec Properties |
|
| 106 |
**********************************************************************/ |
|
| 107 |
void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val) |
|
| 108 |
{
|
|
| 109 |
wax::obj key; std::string name; |
|
| 110 |
boost::tie(key, name) = extract_named_prop(key_); |
|
| 111 |
|
|
| 112 |
//handle the get request conditioned on the key |
|
| 113 |
switch(key.as<codec_prop_t>()) {
|
|
| 114 |
case CODEC_PROP_NAME: |
|
| 115 |
val = std::string("usrp1 dac - ad9862");
|
|
| 116 |
return; |
|
| 117 |
|
|
| 118 |
case CODEC_PROP_OTHERS: |
|
| 119 |
val = prop_names_t(); |
|
| 120 |
return; |
|
| 121 |
|
|
| 122 |
case CODEC_PROP_GAIN_NAMES: |
|
| 123 |
val = prop_names_t(1, ad9862_pga_gain_name); |
|
| 124 |
return; |
|
| 125 |
|
|
| 126 |
case CODEC_PROP_GAIN_RANGE: |
|
| 127 |
UHD_ASSERT_THROW(name == ad9862_pga_gain_name); |
|
| 128 |
val = usrp1_codec_ctrl::tx_pga_gain_range; |
|
| 129 |
return; |
|
| 130 |
|
|
| 131 |
case CODEC_PROP_GAIN_I: //only one gain for I and Q |
|
| 132 |
case CODEC_PROP_GAIN_Q: |
|
| 133 |
UHD_ASSERT_THROW(name == ad9862_pga_gain_name); |
|
| 134 |
val = _codec_ctrl->get_tx_pga_gain(); |
|
| 135 |
return; |
|
| 136 |
|
|
| 137 |
default: UHD_THROW_PROP_GET_ERROR(); |
|
| 138 |
} |
|
| 139 |
} |
|
| 140 |
|
|
| 141 |
void usrp1_impl::tx_codec_set(const wax::obj &, const wax::obj &) |
|
| 142 |
{
|
|
| 143 |
wax::obj key; std::string name; |
|
| 144 |
boost::tie(key, name) = extract_named_prop(key_); |
|
| 145 |
|
|
| 146 |
//handle the set request conditioned on the key |
|
| 147 |
switch(key.as<codec_prop_t>()){
|
|
| 148 |
case CODEC_PROP_GAIN_I: //only one gain for I and Q |
|
| 149 |
case CODEC_PROP_GAIN_Q: |
|
| 150 |
UHD_ASSERT_THROW(name == ad9862_pga_gain_name); |
|
| 151 |
_codec_ctrl->set_tx_pga_gain(val.as<float>()); |
|
| 152 |
return; |
|
| 153 |
|
|
| 154 |
default: UHD_THROW_PROP_SET_ERROR(); |
|
| 155 |
} |
|
| 156 |
} |
|
| b/host/lib/usrp/usrp1/dboard_iface.cpp | ||
|---|---|---|
| 1 |
// |
|
| 2 |
// Copyright 2010 Ettus Research LLC |
|
| 3 |
// |
|
| 4 |
// This program is free software: you can redistribute it and/or modify |
|
| 5 |
// it under the terms of the GNU General Public License as published by |
|
| 6 |
// the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
// (at your option) any later version. |
|
| 8 |
// |
|
| 9 |
// This program is distributed in the hope that it will be useful, |
|
| 10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
// GNU General Public License for more details. |
|
| 13 |
// |
|
| 14 |
// You should have received a copy of the GNU General Public License |
|
| 15 |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 16 |
// |
|
| 17 |
|
|
| 18 |
#include "usrp1_iface.hpp" |
|
| 19 |
#include "fpga_regs_common.h" |
|
| 20 |
#include "usrp_spi_defs.h" |
|
| 21 |
#include "clock_ctrl.hpp" |
|
| 22 |
#include "codec_ctrl.hpp" |
|
| 23 |
#include <uhd/usrp/dboard_iface.hpp> |
|
| 24 |
#include <uhd/types/dict.hpp> |
|
| 25 |
#include <uhd/utils/assert.hpp> |
|
| 26 |
#include <boost/assign/list_of.hpp> |
|
| 27 |
#include <iostream> |
|
| 28 |
|
|
| 29 |
using namespace uhd; |
|
| 30 |
using namespace uhd::usrp; |
|
| 31 |
using namespace boost::assign; |
|
| 32 |
|
|
| 33 |
class usrp1_dboard_iface : public dboard_iface {
|
|
| 34 |
public: |
|
| 35 |
|
|
| 36 |
usrp1_dboard_iface(usrp1_iface::sptr iface, |
|
| 37 |
usrp1_clock_ctrl::sptr clock, |
|
| 38 |
usrp1_codec_ctrl::sptr codec) |
|
| 39 |
{
|
|
| 40 |
_iface = iface; |
|
| 41 |
_clock = clock; |
|
| 42 |
_codec = codec; |
|
| 43 |
|
|
| 44 |
//init the clock rate shadows |
|
| 45 |
this->set_clock_rate(UNIT_RX, _clock->get_master_clock_freq()); |
|
| 46 |
this->set_clock_rate(UNIT_TX, _clock->get_master_clock_freq()); |
|
| 47 |
} |
|
| 48 |
|
|
| 49 |
~usrp1_dboard_iface() |
|
| 50 |
{
|
|
| 51 |
/* NOP */ |
|
| 52 |
} |
|
| 53 |
|
|
| 54 |
std::string get_mboard_name() |
|
| 55 |
{
|
|
| 56 |
return "usrp1"; |
|
| 57 |
} |
|
| 58 |
|
|
| 59 |
void write_aux_dac(unit_t, aux_dac_t, float); |
|
| 60 |
float read_aux_adc(unit_t, aux_adc_t); |
|
| 61 |
|
|
| 62 |
void set_pin_ctrl(unit_t, boost::uint16_t); |
|
| 63 |
void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); |
|
| 64 |
void set_gpio_ddr(unit_t, boost::uint16_t); |
|
| 65 |
void write_gpio(unit_t, boost::uint16_t); |
|
| 66 |
boost::uint16_t read_gpio(unit_t); |
|
| 67 |
|
|
| 68 |
void write_i2c(boost::uint8_t, const byte_vector_t &); |
|
| 69 |
byte_vector_t read_i2c(boost::uint8_t, size_t); |
|
| 70 |
|
|
| 71 |
void write_spi(unit_t unit, |
|
| 72 |
const spi_config_t &config, |
|
| 73 |
boost::uint32_t data, |
|
| 74 |
size_t num_bits); |
|
| 75 |
|
|
| 76 |
boost::uint32_t read_write_spi(unit_t unit, |
|
| 77 |
const spi_config_t &config, |
|
| 78 |
boost::uint32_t data, |
|
| 79 |
size_t num_bits); |
|
| 80 |
|
|
| 81 |
void set_clock_rate(unit_t, double); |
|
| 82 |
std::vector<double> get_clock_rates(unit_t); |
|
| 83 |
double get_clock_rate(unit_t); |
|
| 84 |
void set_clock_enabled(unit_t, bool); |
|
| 85 |
|
|
| 86 |
private: |
|
| 87 |
usrp1_iface::sptr _iface; |
|
| 88 |
usrp1_clock_ctrl::sptr _clock; |
|
| 89 |
usrp1_codec_ctrl::sptr _codec; |
|
| 90 |
uhd::dict<unit_t, double> _clock_rates; |
|
| 91 |
}; |
|
| 92 |
|
|
| 93 |
/*********************************************************************** |
|
| 94 |
* Make Function |
|
| 95 |
**********************************************************************/ |
|
| 96 |
dboard_iface::sptr make_usrp1_dboard_iface(usrp1_iface::sptr iface, |
|
| 97 |
usrp1_clock_ctrl::sptr clock, |
|
| 98 |
usrp1_codec_ctrl::sptr codec) |
|
| 99 |
{
|
|
| 100 |
return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec)); |
|
| 101 |
} |
|
| 102 |
|
|
| 103 |
/*********************************************************************** |
|
| 104 |
* Clock Rates |
|
| 105 |
**********************************************************************/ |
|
| 106 |
void usrp1_dboard_iface::set_clock_rate(unit_t unit, double rate) |
|
| 107 |
{
|
|
| 108 |
_clock_rates[unit] = rate; |
|
| 109 |
switch(unit) {
|
|
| 110 |
case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate); |
|
| 111 |
case UNIT_TX: return _clock->set_tx_dboard_clock_rate(rate); |
|
| 112 |
} |
|
| 113 |
} |
|
| 114 |
|
|
| 115 |
/* |
|
| 116 |
* TODO: if this is a dbsrx return the rate of 4MHZ and set FPGA magic |
|
| 117 |
*/ |
|
| 118 |
std::vector<double> usrp1_dboard_iface::get_clock_rates(unit_t unit) |
|
| 119 |
{
|
|
| 120 |
switch(unit) {
|
|
| 121 |
case UNIT_RX: return _clock->get_rx_dboard_clock_rates(); |
|
| 122 |
case UNIT_TX: return _clock->get_tx_dboard_clock_rates(); |
|
| 123 |
default: UHD_THROW_INVALID_CODE_PATH(); |
|
| 124 |
} |
|
| 125 |
} |
|
| 126 |
|
|
| 127 |
double usrp1_dboard_iface::get_clock_rate(unit_t unit) |
|
| 128 |
{
|
|
| 129 |
return _clock_rates[unit]; |
|
| 130 |
} |
|
| 131 |
|
|
| 132 |
void usrp1_dboard_iface::set_clock_enabled(unit_t unit, bool enb) |
|
| 133 |
{
|
|
| 134 |
switch(unit) {
|
|
| 135 |
case UNIT_RX: return _clock->enable_rx_dboard_clock(enb); |
|
| 136 |
case UNIT_TX: return _clock->enable_tx_dboard_clock(enb); |
|
| 137 |
} |
|
| 138 |
} |
|
| 139 |
|
|
| 140 |
/*********************************************************************** |
|
| 141 |
* GPIO |
|
| 142 |
**********************************************************************/ |
|
| 143 |
void usrp1_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value) |
|
| 144 |
{
|
|
| 145 |
switch(unit) {
|
|
| 146 |
case UNIT_RX: |
|
| 147 |
_iface->poke32(FR_ATR_MASK_1, value); |
|
| 148 |
_iface->poke32(FR_ATR_MASK_3, 0x00000000); |
|
| 149 |
break; |
|
| 150 |
case UNIT_TX: |
|
| 151 |
_iface->poke32(FR_ATR_MASK_0, value); |
|
| 152 |
_iface->poke32(FR_ATR_MASK_2, 0x00000000); |
|
| 153 |
break; |
|
| 154 |
} |
|
| 155 |
} |
|
| 156 |
|
|
| 157 |
void usrp1_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value) |
|
| 158 |
{
|
|
| 159 |
switch(unit) {
|
|
| 160 |
case UNIT_RX: |
|
| 161 |
_iface->poke32(FR_OE_1, 0xffff0000 | value); |
|
| 162 |
_iface->poke32(FR_OE_3, 0xffff0000); |
|
| 163 |
break; |
|
| 164 |
case UNIT_TX: |
|
| 165 |
_iface->poke32(FR_OE_0, 0xffff0000 | value); |
|
| 166 |
_iface->poke32(FR_OE_2, 0xffff0000); |
|
| 167 |
break; |
|
| 168 |
} |
|
| 169 |
} |
|
| 170 |
|
|
| 171 |
void usrp1_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value) |
|
| 172 |
{
|
|
| 173 |
switch(unit) {
|
|
| 174 |
case UNIT_RX: |
|
| 175 |
_iface->poke32(FR_IO_1, 0xffff0000 | value); |
|
| 176 |
break; |
|
| 177 |
case UNIT_TX: |
|
| 178 |
_iface->poke32(FR_IO_0, 0xffff0000 | value); |
|
| 179 |
break; |
|
| 180 |
} |
|
| 181 |
} |
|
| 182 |
|
|
| 183 |
boost::uint16_t usrp1_dboard_iface::read_gpio(unit_t unit) |
|
| 184 |
{
|
|
| 185 |
boost::uint32_t out_value; |
|
| 186 |
boost::uint16_t ret_value; |
|
| 187 |
|
|
| 188 |
switch(unit) {
|
|
| 189 |
case UNIT_RX: |
|
| 190 |
//magic |
|
| 191 |
out_value = _iface->peek32(1); |
|
| 192 |
ret_value = (out_value >> 16) & 0x0000ffff; |
|
| 193 |
return ret_value; |
|
| 194 |
case UNIT_TX: |
|
| 195 |
//magic |
|
| 196 |
out_value = _iface->peek32(1); |
|
| 197 |
ret_value = (out_value >> 0) & 0x0000ffff; |
|
| 198 |
return ret_value; |
|
| 199 |
} |
|
| 200 |
UHD_ASSERT_THROW(false); |
|
| 201 |
} |
|
| 202 |
|
|
| 203 |
void usrp1_dboard_iface::set_atr_reg(unit_t unit, |
|
| 204 |
atr_reg_t atr, boost::uint16_t value) |
|
| 205 |
{
|
|
| 206 |
if ((atr == ATR_REG_IDLE) || (atr == ATR_REG_FULL_DUPLEX)) {
|
|
| 207 |
std::cerr << "error: set_atr_reg(): unsupported state" << std::endl; |
|
| 208 |
return; |
|
| 209 |
} |
|
| 210 |
|
|
| 211 |
switch(unit) {
|
|
| 212 |
case UNIT_RX: |
|
| 213 |
_iface->poke32(FR_ATR_RXVAL_1, value); |
|
| 214 |
_iface->poke32(FR_ATR_RXVAL_3, 0x0000); |
|
| 215 |
break; |
|
| 216 |
case UNIT_TX: |
|
| 217 |
//_iface->poke32(FR_ATR_TXVAL_0, value); |
|
| 218 |
_iface->poke32(FR_ATR_TXVAL_0, 0x0000); |
|
| 219 |
_iface->poke32(FR_ATR_TXVAL_2, 0x0000); |
|
| 220 |
break; |
|
| 221 |
} |
|
| 222 |
} |
|
| 223 |
/*********************************************************************** |
|
| 224 |
* SPI |
|
| 225 |
**********************************************************************/ |
|
| 226 |
/*! |
|
| 227 |
* Static function to convert a unit type to a spi slave device number. |
|
| 228 |
* \param unit the dboard interface unit type enum |
|
| 229 |
* \return the slave device number |
|
| 230 |
*/ |
|
| 231 |
static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit) |
|
| 232 |
{
|
|
| 233 |
switch(unit) {
|
|
| 234 |
case dboard_iface::UNIT_TX: return SPI_ENABLE_TX_A; |
|
| 235 |
case dboard_iface::UNIT_RX: return SPI_ENABLE_RX_A; |
|
| 236 |
} |
|
| 237 |
throw std::invalid_argument("unknown unit type");
|
|
| 238 |
|
|
| 239 |
} |
|
| 240 |
|
|
| 241 |
void usrp1_dboard_iface::write_spi(unit_t unit, |
|
| 242 |
const spi_config_t &config, |
|
| 243 |
boost::uint32_t data, |
|
| 244 |
size_t num_bits) |
|
| 245 |
{
|
|
| 246 |
_iface->transact_spi(unit_to_otw_spi_dev(unit), |
|
| 247 |
config, data, num_bits, false); |
|
| 248 |
} |
|
| 249 |
|
|
| 250 |
boost::uint32_t usrp1_dboard_iface::read_write_spi(unit_t unit, |
|
| 251 |
const spi_config_t &config, |
|
| 252 |
boost::uint32_t data, |
|
| 253 |
size_t num_bits) |
|
| 254 |
{
|
|
| 255 |
return _iface->transact_spi(unit_to_otw_spi_dev(unit), |
|
| 256 |
config, data, num_bits, true); |
|
| 257 |
} |
|
| 258 |
|
|
| 259 |
/*********************************************************************** |
|
| 260 |
* I2C |
|
| 261 |
**********************************************************************/ |
|
| 262 |
void usrp1_dboard_iface::write_i2c(boost::uint8_t addr, |
|
| 263 |
const byte_vector_t &bytes) |
|
| 264 |
{
|
|
| 265 |
return _iface->write_i2c(addr, bytes); |
|
| 266 |
} |
|
| 267 |
|
|
| 268 |
byte_vector_t usrp1_dboard_iface::read_i2c(boost::uint8_t addr, |
|
| 269 |
size_t num_bytes) |
|
| 270 |
{
|
|
| 271 |
return _iface->read_i2c(addr, num_bytes); |
|
| 272 |
} |
|
| 273 |
|
|
| 274 |
/*********************************************************************** |
|
| 275 |
* Aux DAX/ADC |
|
| 276 |
**********************************************************************/ |
|
| 277 |
void usrp1_dboard_iface::write_aux_dac(dboard_iface::unit_t, |
|
| 278 |
aux_dac_t which, float value) |
|
| 279 |
{
|
|
| 280 |
//same aux dacs for each unit |
|
| 281 |
static const uhd::dict<aux_dac_t, usrp1_codec_ctrl::aux_dac_t> |
|
| 282 |
which_to_aux_dac = map_list_of |
|
| 283 |
(AUX_DAC_A, usrp1_codec_ctrl::AUX_DAC_A) |
|
| 284 |
(AUX_DAC_B, usrp1_codec_ctrl::AUX_DAC_B) |
|
| 285 |
(AUX_DAC_C, usrp1_codec_ctrl::AUX_DAC_C) |
|
| 286 |
(AUX_DAC_D, usrp1_codec_ctrl::AUX_DAC_D); |
|
| 287 |
|
|
| 288 |
_codec->write_aux_dac(which_to_aux_dac[which], value); |
|
| 289 |
} |
|
| 290 |
|
|
| 291 |
float usrp1_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, |
|
| 292 |
aux_adc_t which) |
|
| 293 |
{
|
|
| 294 |
static const |
|
| 295 |
uhd::dict<unit_t, uhd::dict<aux_adc_t, usrp1_codec_ctrl::aux_adc_t> > |
|
| 296 |
unit_to_which_to_aux_adc = map_list_of(UNIT_RX, map_list_of |
|
| 297 |
(AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A1) |
|
| 298 |
(AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B1)) |
|
| 299 |
(UNIT_TX, map_list_of |
|
| 300 |
(AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A2) |
|
| 301 |
(AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B2)); |
|
| 302 |
|
|
| 303 |
return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]); |
|
| 304 |
} |
|
| b/host/lib/usrp/usrp1/dboard_impl.cpp | ||
|---|---|---|
| 1 |
// |
|
| 2 |
// Copyright 2010 Ettus Research LLC |
|
| 3 |
// |
|
| 4 |
// This program is free software: you can redistribute it and/or modify |
|
| 5 |
// it under the terms of the GNU General Public License as published by |
|
| 6 |
// the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
// (at your option) any later version. |
|
| 8 |
// |
|
| 9 |
// This program is distributed in the hope that it will be useful, |
|
| 10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
// GNU General Public License for more details. |
|
| 13 |
// |
|
| 14 |
// You should have received a copy of the GNU General Public License |
|
| 15 |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 16 |
// |
|
| 17 |
|
|
| 18 |
#include "usrp1_impl.hpp" |
|
| 19 |
#include "usrp_i2c_addr.h" |
|
| 20 |
#include "../dsp_utils.hpp" |
|
| 21 |
#include "../misc_utils.hpp" |
|
| 22 |
#include <uhd/utils/assert.hpp> |
|
| 23 |
#include <uhd/usrp/dboard_props.hpp> |
|
| 24 |
#include <uhd/usrp/subdev_props.hpp> |
|
| 25 |
#include <boost/bind.hpp> |
|
| 26 |
#include <iostream> |
|
| 27 |
|
|
| 28 |
using namespace uhd; |
|
| 29 |
using namespace uhd::usrp; |
|
| 30 |
|
|
| 31 |
/*********************************************************************** |
|
| 32 |
* Dboard Initialization |
|
| 33 |
**********************************************************************/ |
|
| 34 |
void usrp1_impl::dboard_init(void) |
|
| 35 |
{
|
|
| 36 |
_rx_db_eeprom = dboard_eeprom_t( |
|
| 37 |
_iface->read_eeprom(I2C_ADDR_RX_A, 0, dboard_eeprom_t::num_bytes())); |
|
| 38 |
|
|
| 39 |
_tx_db_eeprom = dboard_eeprom_t( |
|
| 40 |
_iface->read_eeprom(I2C_ADDR_TX_A, 0, dboard_eeprom_t::num_bytes())); |
|
| 41 |
|
|
| 42 |
|
|
| 43 |
//create a new dboard interface and manager |
|
| 44 |
_dboard_iface = make_usrp1_dboard_iface(_iface, _clock_ctrl, _codec_ctrl); |
|
| 45 |
|
|
| 46 |
_dboard_manager = dboard_manager::make(_rx_db_eeprom.id, |
|
| 47 |
_tx_db_eeprom.id, |
|
| 48 |
_dboard_iface); |
|
| 49 |
|
|
| 50 |
//setup the dboard proxies |
|
| 51 |
_rx_dboard_proxy = wax_obj_proxy::make( |
|
| 52 |
boost::bind(&usrp1_impl::rx_dboard_get, this, _1, _2), |
|
| 53 |
boost::bind(&usrp1_impl::rx_dboard_set, this, _1, _2)); |
|
| 54 |
|
|
| 55 |
_tx_dboard_proxy = wax_obj_proxy::make( |
|
| 56 |
boost::bind(&usrp1_impl::tx_dboard_get, this, _1, _2), |
|
| 57 |
boost::bind(&usrp1_impl::tx_dboard_set, this, _1, _2)); |
|
| 58 |
|
|
| 59 |
} |
|
| 60 |
/*********************************************************************** |
|
| 61 |
* Helper functions |
|
| 62 |
**********************************************************************/ |
|
| 63 |
//static int slot_to_i2c_addr (int slot) |
|
| 64 |
//{
|
|
| 65 |
// switch (slot) {
|
|
| 66 |
// case SLOT_TX_A: |
|
| 67 |
// return I2C_ADDR_TX_A; |
|
| 68 |
// case SLOT_RX_A: |
|
| 69 |
// return I2C_ADDR_RX_A; |
|
| 70 |
// case SLOT_TX_B: |
|
| 71 |
// return I2C_ADDR_TX_B; |
|
| 72 |
// case SLOT_RX_B: |
|
| 73 |
// return I2C_ADDR_RX_B; |
|
| 74 |
// default: |
|
| 75 |
// return -1; |
|
| 76 |
// } |
|
| 77 |
//} |
|
| 78 |
|
|
| 79 |
|
|
| 80 |
/*********************************************************************** |
|
| 81 |
* RX Dboard Get |
|
| 82 |
**********************************************************************/ |
|
| 83 |
void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val) |
|
| 84 |
{
|
|
| 85 |
wax::obj key; std::string name; |
|
| 86 |
boost::tie(key, name) = extract_named_prop(key_); |
|
| 87 |
|
|
| 88 |
//handle the get request conditioned on the key |
|
| 89 |
switch(key.as<dboard_prop_t>()){
|
|
| 90 |
case DBOARD_PROP_NAME: |
|
| 91 |
val = std::string("usrp1 dboard (rx unit)");
|
|
| 92 |
return; |
|
| 93 |
|
|
| 94 |
case DBOARD_PROP_SUBDEV: |
|
| 95 |
val = _dboard_manager->get_rx_subdev(name); |
|
| 96 |
return; |
|
| 97 |
|
|
| 98 |
case DBOARD_PROP_SUBDEV_NAMES: |
|
| 99 |
val = _dboard_manager->get_rx_subdev_names(); |
|
| 100 |
return; |
|
| 101 |
|
|
| 102 |
case DBOARD_PROP_DBOARD_ID: |
|
| 103 |
val = _rx_db_eeprom.id; |
|
| 104 |
return; |
|
| 105 |
|
|
| 106 |
case DBOARD_PROP_DBOARD_IFACE: |
|
| 107 |
val = _dboard_iface; |
|
| 108 |
return; |
|
| 109 |
|
|
| 110 |
case DBOARD_PROP_CODEC: |
|
| 111 |
val = _rx_codec_proxy->get_link(); |
|
| 112 |
return; |
|
| 113 |
|
|
| 114 |
case DBOARD_PROP_GAIN_GROUP: |
|
| 115 |
val = make_gain_group(_dboard_manager->get_rx_subdev(name), |
|
| 116 |
_rx_codec_proxy->get_link()); |
|
| 117 |
return; |
|
| 118 |
|
|
| 119 |
default: UHD_THROW_PROP_GET_ERROR(); |
|
| 120 |
} |
|
| 121 |
} |
|
| 122 |
|
|
| 123 |
/*********************************************************************** |
|
| 124 |
* RX Dboard Set |
|
| 125 |
**********************************************************************/ |
|
| 126 |
void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val) |
|
| 127 |
{
|
|
| 128 |
switch(key.as<dboard_prop_t>()) {
|
|
| 129 |
case DBOARD_PROP_DBOARD_ID: |
|
| 130 |
_rx_db_eeprom.id = val.as<dboard_id_t>(); |
|
| 131 |
_iface->write_eeprom(I2C_ADDR_RX_A, 0, |
|
| 132 |
_rx_db_eeprom.get_eeprom_bytes()); |
|
| 133 |
return; |
|
| 134 |
|
|
| 135 |
default: |
|
| 136 |
UHD_THROW_PROP_SET_ERROR(); |
|
| 137 |
} |
|
| 138 |
} |
|
| 139 |
|
|
| 140 |
/*********************************************************************** |
|
| 141 |
* TX Dboard Get |
|
| 142 |
**********************************************************************/ |
|
| 143 |
void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val) |
|
| 144 |
{
|
|
| 145 |
wax::obj key; std::string name; |
|
| 146 |
boost::tie(key, name) = extract_named_prop(key_); |
|
| 147 |
|
|
| 148 |
//handle the get request conditioned on the key |
|
| 149 |
switch(key.as<dboard_prop_t>()){
|
|
| 150 |
case DBOARD_PROP_NAME: |
|
| 151 |
val = std::string("usrp1 dboard (tx unit)");
|
|
| 152 |
return; |
|
| 153 |
|
|
| 154 |
case DBOARD_PROP_SUBDEV: |
|
| 155 |
val = _dboard_manager->get_tx_subdev(name); |
|
| 156 |
return; |
|
| 157 |
|
|
| 158 |
case DBOARD_PROP_SUBDEV_NAMES: |
|
| 159 |
val = _dboard_manager->get_tx_subdev_names(); |
|
| 160 |
return; |
|
| 161 |
|
|
| 162 |
case DBOARD_PROP_DBOARD_ID: |
|
| 163 |
val = _tx_db_eeprom.id; |
|
| 164 |
return; |
|
| 165 |
|
|
| 166 |
case DBOARD_PROP_DBOARD_IFACE: |
|
| 167 |
val = _dboard_iface; |
|
| 168 |
return; |
|
| 169 |
|
|
| 170 |
case DBOARD_PROP_CODEC: |
|
| 171 |
val = _tx_codec_proxy->get_link(); |
|
| 172 |
return; |
|
| 173 |
|
|
| 174 |
case DBOARD_PROP_GAIN_GROUP: |
|
| 175 |
val = make_gain_group(_dboard_manager->get_tx_subdev(name), |
|
| 176 |
_tx_codec_proxy->get_link()); |
|
| 177 |
return; |
|
| 178 |
|
|
| 179 |
default: UHD_THROW_PROP_GET_ERROR(); |
|
| 180 |
} |
|
| 181 |
} |
|
| 182 |
|
|
| 183 |
/*********************************************************************** |
|
| 184 |
* TX Dboard Set |
|
| 185 |
**********************************************************************/ |
|
| 186 |
void usrp1_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val) |
|
| 187 |
{
|
|
| 188 |
switch(key.as<dboard_prop_t>()) {
|
|
| 189 |
case DBOARD_PROP_DBOARD_ID: |
|
| 190 |
_tx_db_eeprom.id = val.as<dboard_id_t>(); |
|
| 191 |
_iface->write_eeprom(I2C_ADDR_TX_A, 0, _tx_db_eeprom.get_eeprom_bytes()); |
|
| 192 |
return; |
|
| 193 |
|
|
| 194 |
default: UHD_THROW_PROP_SET_ERROR(); |
|
| 195 |
} |
|
| 196 |
} |
|
| b/host/lib/usrp/usrp1/dsp_impl.cpp | ||
|---|---|---|
| 1 |
// |
|
| 2 |
// Copyright 2010 Ettus Research LLC |
|
| 3 |
// |
|
| 4 |
// This program is free software: you can redistribute it and/or modify |
|
| 5 |
// it under the terms of the GNU General Public License as published by |
|
| 6 |
// the Free Software Foundation, either version 3 of the License, or |
|
| 7 |
// (at your option) any later version. |
|
Also available in: Unified diff