summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/usrp/dboard_iface.hpp39
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp2
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp2
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp2
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.cpp47
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.hpp27
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp61
7 files changed, 150 insertions, 30 deletions
diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp
index 7ecfcd3c0..caf1e6ee6 100644
--- a/host/include/uhd/usrp/dboard_iface.hpp
+++ b/host/include/uhd/usrp/dboard_iface.hpp
@@ -22,6 +22,7 @@
#include <uhd/types/serial.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/cstdint.hpp>
+#include <vector>
namespace uhd{ namespace usrp{
@@ -35,13 +36,13 @@ class UHD_API dboard_iface{
public:
typedef boost::shared_ptr<dboard_iface> sptr;
- //tells the host which unit to use
+ //! tells the host which unit to use
enum unit_t{
UNIT_RX = 'r',
UNIT_TX = 't'
};
- //possible atr registers
+ //! possible atr registers
enum atr_reg_t{
ATR_REG_IDLE = 'i',
ATR_REG_TX_ONLY = 't',
@@ -49,6 +50,20 @@ public:
ATR_REG_FULL_DUPLEX = 'f'
};
+ //! aux dac selection enums (per unit)
+ enum aux_dac_t{
+ AUX_DAC_A = 'a',
+ AUX_DAC_B = 'b',
+ AUX_DAC_C = 'c',
+ AUX_DAC_D = 'd'
+ };
+
+ //! aux adc selection enums (per unit)
+ enum aux_adc_t{
+ AUX_ADC_A = 'a',
+ AUX_ADC_B = 'b'
+ };
+
/*!
* Write to an aux dac.
*
@@ -56,7 +71,7 @@ public:
* \param which_dac the dac index 0, 1, 2, 3...
* \param value the value in volts
*/
- virtual void write_aux_dac(unit_t unit, int which_dac, float value) = 0;
+ virtual void write_aux_dac(unit_t unit, aux_dac_t which_dac, float value) = 0;
/*!
* Read from an aux adc.
@@ -65,7 +80,7 @@ public:
* \param which_adc the adc index 0, 1, 2, 3...
* \return the value in volts
*/
- virtual float read_aux_adc(unit_t unit, int which_adc) = 0;
+ virtual float read_aux_adc(unit_t unit, aux_adc_t which_adc) = 0;
/*!
* Set a daughterboard output pin control source.
@@ -159,6 +174,14 @@ public:
) = 0;
/*!
+ * Set the rate of a dboard clock.
+ *
+ * \param unit which unit rx or tx
+ * \param rate the clock rate in Hz
+ */
+ virtual void set_clock_rate(unit_t unit, double rate) = 0;
+
+ /*!
* Get the rate of a dboard clock.
*
* \param unit which unit rx or tx
@@ -167,6 +190,14 @@ public:
virtual double get_clock_rate(unit_t unit) = 0;
/*!
+ * Get a list of possible rates for the dboard clock.
+ *
+ * \param unit which unit rx or tx
+ * \return a list of clock rates in Hz
+ */
+ virtual std::vector<double> get_clock_rates(unit_t unit) = 0;
+
+ /*!
* Enable or disable a dboard clock.
*
* \param unit which unit rx or tx
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 2585dfa8d..7f2275b07 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -257,7 +257,7 @@ void rfx_xcvr::set_rx_gain(float gain, const std::string &name){
_rx_gains[name] = gain;
//write the new voltage to the aux dac
- this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, 0, dac_volts);
+ this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, dac_volts);
}
else UHD_THROW_INVALID_CODE_PATH();
}
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index 95dcb3802..aa5daf9a3 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -246,7 +246,7 @@ void wbx_xcvr::set_tx_gain(float gain, const std::string &name){
_tx_gains[name] = gain;
//write the new voltage to the aux dac
- this->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, 0, dac_volts);
+ this->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, dboard_iface::AUX_DAC_A, dac_volts);
}
else UHD_THROW_INVALID_CODE_PATH();
}
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index 974a378bd..d83781965 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -144,7 +144,7 @@ private:
static const float min_v = float(0.5), max_v = float(2.5);
static const float rssi_dyn_range = 60;
//calculate the rssi from the voltage
- float voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, 1);
+ float voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B);
return rssi_dyn_range*(voltage - min_v)/(max_v - min_v);
}
};
diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp
index d9baa66cf..59fac6fcf 100644
--- a/host/lib/usrp/usrp2/clock_ctrl.cpp
+++ b/host/lib/usrp/usrp2/clock_ctrl.cpp
@@ -18,6 +18,7 @@
#include "clock_ctrl.hpp"
#include "ad9510_regs.hpp"
#include "usrp2_regs.hpp" //spi slave constants
+#include <uhd/utils/assert.hpp>
#include <boost/cstdint.hpp>
using namespace uhd;
@@ -60,7 +61,9 @@ public:
this->enable_external_ref(false);
this->enable_rx_dboard_clock(false);
+ this->set_rate_rx_dboard_clock(get_rates_rx_dboard_clock().at(0));
this->enable_tx_dboard_clock(false);
+ this->set_rate_tx_dboard_clock(get_rates_tx_dboard_clock().at(0));
/* private clock enables, must be set here */
this->enable_dac_clock(true);
@@ -79,23 +82,63 @@ public:
_ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1;
_ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS;
_ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA;
- _ad9510_regs.bypass_divider_out7 = 1;
this->write_reg(0x43);
+ this->update_regs();
+ }
+
+ void set_rate_rx_dboard_clock(double rate){
+ assert_has(get_rates_rx_dboard_clock(), rate, "rx dboard clock rate");
+ size_t divider = size_t(rate/get_master_clock_rate());
+ //bypass when the divider ratio is one
+ _ad9510_regs.bypass_divider_out7 = (divider == 1)? 1 : 0;
+ //calculate the low and high dividers
+ size_t high = divider/2;
+ size_t low = divider - high;
+ //set the registers (divider - 1)
+ _ad9510_regs.divider_low_cycles_out7 = low - 1;
+ _ad9510_regs.divider_high_cycles_out7 = high - 1;
+ //write the registers
+ this->write_reg(0x56);
this->write_reg(0x57);
this->update_regs();
}
+ std::vector<double> get_rates_rx_dboard_clock(void){
+ std::vector<double> rates;
+ for (size_t i = 1; i <= 16+16; i++) rates.push_back(get_master_clock_rate()/i);
+ return rates;
+ }
+
//uses output clock 6 (cmos)
void enable_tx_dboard_clock(bool enb){
_ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1;
_ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS;
_ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA;
- _ad9510_regs.bypass_divider_out6 = 1;
this->write_reg(0x42);
+ this->update_regs();
+ }
+
+ void set_rate_tx_dboard_clock(double rate){
+ assert_has(get_rates_tx_dboard_clock(), rate, "tx dboard clock rate");
+ size_t divider = size_t(rate/get_master_clock_rate());
+ //bypass when the divider ratio is one
+ _ad9510_regs.bypass_divider_out6 = (divider == 1)? 1 : 0;
+ //calculate the low and high dividers
+ size_t high = divider/2;
+ size_t low = divider - high;
+ //set the registers (divider - 1)
+ _ad9510_regs.divider_low_cycles_out6 = low - 1;
+ _ad9510_regs.divider_high_cycles_out6 = high - 1;
+ //write the registers
+ this->write_reg(0x54);
this->write_reg(0x55);
this->update_regs();
}
+ std::vector<double> get_rates_tx_dboard_clock(void){
+ return get_rates_rx_dboard_clock(); //same master clock, same dividers...
+ }
+
/*!
* If we are to use an external reference, enable the charge pump.
* \param enb true to enable the CP
diff --git a/host/lib/usrp/usrp2/clock_ctrl.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp
index 0ad8d9532..70a104a81 100644
--- a/host/lib/usrp/usrp2/clock_ctrl.hpp
+++ b/host/lib/usrp/usrp2/clock_ctrl.hpp
@@ -21,6 +21,7 @@
#include "usrp2_iface.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
+#include <vector>
class usrp2_clock_ctrl : boost::noncopyable{
public:
@@ -46,12 +47,38 @@ public:
virtual void enable_rx_dboard_clock(bool enb) = 0;
/*!
+ * Set the clock rate on the rx dboard clock.
+ * \param rate the new clock rate
+ * \throw exception when rate invalid
+ */
+ virtual void set_rate_rx_dboard_clock(double rate) = 0;
+
+ /*!
+ * Get a list of possible rx dboard clock rates.
+ * \return a list of clock rates in Hz
+ */
+ virtual std::vector<double> get_rates_rx_dboard_clock(void) = 0;
+
+ /*!
* Enable/disable the tx dboard clock.
* \param enb true to enable
*/
virtual void enable_tx_dboard_clock(bool enb) = 0;
/*!
+ * Set the clock rate on the tx dboard clock.
+ * \param rate the new clock rate
+ * \throw exception when rate invalid
+ */
+ virtual void set_rate_tx_dboard_clock(double rate) = 0;
+
+ /*!
+ * Get a list of possible tx dboard clock rates.
+ * \return a list of clock rates in Hz
+ */
+ virtual std::vector<double> get_rates_tx_dboard_clock(void) = 0;
+
+ /*!
* Enable/disable external reference.
* \param enb true to enable
*/
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index 114f83f41..ec6c98186 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -36,8 +36,8 @@ public:
usrp2_dboard_iface(usrp2_iface::sptr iface, usrp2_clock_ctrl::sptr clock_ctrl);
~usrp2_dboard_iface(void);
- void write_aux_dac(unit_t, int, float);
- float read_aux_adc(unit_t, int);
+ void write_aux_dac(unit_t, aux_dac_t, float);
+ float read_aux_adc(unit_t, aux_adc_t);
void set_pin_ctrl(unit_t, boost::uint16_t);
void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
@@ -48,9 +48,10 @@ public:
void write_i2c(boost::uint8_t, const byte_vector_t &);
byte_vector_t read_i2c(boost::uint8_t, size_t);
+ void set_clock_rate(unit_t, double);
double get_clock_rate(unit_t);
+ std::vector<double> get_clock_rates(unit_t);
void set_clock_enabled(unit_t, bool);
- bool get_clock_enabled(unit_t);
void write_spi(
unit_t unit,
@@ -73,6 +74,7 @@ private:
boost::uint32_t _gpio_shadow;
uhd::dict<unit_t, ad5623_regs_t> _dac_regs;
+ uhd::dict<unit_t, double> _clock_rates;
void _write_aux_dac(unit_t);
};
@@ -116,8 +118,24 @@ usrp2_dboard_iface::~usrp2_dboard_iface(void){
/***********************************************************************
* Clocks
**********************************************************************/
-double usrp2_dboard_iface::get_clock_rate(unit_t){
- return _clock_ctrl->get_master_clock_rate();
+void usrp2_dboard_iface::set_clock_rate(unit_t unit, double rate){
+ _clock_rates[unit] = rate; //set to shadow
+ switch(unit){
+ case UNIT_RX: _clock_ctrl->set_rate_rx_dboard_clock(rate); return;
+ case UNIT_TX: _clock_ctrl->set_rate_tx_dboard_clock(rate); return;
+ }
+}
+
+double usrp2_dboard_iface::get_clock_rate(unit_t unit){
+ return _clock_rates[unit]; //get from shadow
+}
+
+std::vector<double> usrp2_dboard_iface::get_clock_rates(unit_t unit){
+ switch(unit){
+ case UNIT_RX: return _clock_ctrl->get_rates_rx_dboard_clock();
+ case UNIT_TX: return _clock_ctrl->get_rates_tx_dboard_clock();
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
}
void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){
@@ -240,31 +258,30 @@ void usrp2_dboard_iface::_write_aux_dac(unit_t unit){
);
}
-void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, float value){
+void usrp2_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, float value){
_dac_regs[unit].data = boost::math::iround(4095*value/3.3);
_dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N;
- //standardize on USRP1 interface, A=0, B=1, C=2, D=3
- static const uhd::dict<
- unit_t, uhd::dict<int, ad5623_regs_t::addr_t>
- > unit_to_which_to_addr = map_list_of
+
+ typedef uhd::dict<aux_dac_t, ad5623_regs_t::addr_t> aux_dac_to_addr;
+ static const uhd::dict<unit_t, aux_dac_to_addr> unit_to_which_to_addr = map_list_of
(UNIT_RX, map_list_of
- (0, ad5623_regs_t::ADDR_DAC_B)
- (1, ad5623_regs_t::ADDR_DAC_A)
- (2, ad5623_regs_t::ADDR_DAC_A)
- (3, ad5623_regs_t::ADDR_DAC_B)
+ (AUX_DAC_A, ad5623_regs_t::ADDR_DAC_B)
+ (AUX_DAC_B, ad5623_regs_t::ADDR_DAC_A)
+ (AUX_DAC_C, ad5623_regs_t::ADDR_DAC_A)
+ (AUX_DAC_D, ad5623_regs_t::ADDR_DAC_B)
)
(UNIT_TX, map_list_of
- (0, ad5623_regs_t::ADDR_DAC_A)
- (1, ad5623_regs_t::ADDR_DAC_B)
- (2, ad5623_regs_t::ADDR_DAC_B)
- (3, ad5623_regs_t::ADDR_DAC_A)
+ (AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A)
+ (AUX_DAC_B, ad5623_regs_t::ADDR_DAC_B)
+ (AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B)
+ (AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A)
)
;
_dac_regs[unit].addr = unit_to_which_to_addr[unit][which];
this->_write_aux_dac(unit);
}
-float usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){
+float usrp2_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which){
static const uhd::dict<unit_t, int> unit_to_spi_adc = map_list_of
(UNIT_RX, SPI_SS_RX_ADC)
(UNIT_TX, SPI_SS_TX_ADC)
@@ -277,8 +294,10 @@ float usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){
//setup the spi registers
ad7922_regs_t ad7922_regs;
- ad7922_regs.mod = which; //normal mode: mod == chn
- ad7922_regs.chn = which;
+ switch(which){
+ case AUX_ADC_A: ad7922_regs.mod = 0; break;
+ case AUX_ADC_B: ad7922_regs.mod = 1; break;
+ } ad7922_regs.chn = ad7922_regs.mod; //normal mode: mod == chn
//write and read spi
_iface->transact_spi(