From f57f616cfd6406cd67681813d464695c8c160f9e Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Wed, 14 Apr 2010 17:19:27 -0700
Subject: Added gain control to rfx. Switched string constants to caps (gains,
 antennas, subdevs). Made dboard interface for aux dac and adc use volts.

---
 host/lib/usrp/dboard/db_basic_and_lf.cpp |  6 ++--
 host/lib/usrp/dboard/db_rfx.cpp          | 47 ++++++++++++++++++++++++--------
 host/lib/usrp/usrp2/dboard_iface.cpp     | 13 +++++----
 3 files changed, 46 insertions(+), 20 deletions(-)

(limited to 'host/lib/usrp')

diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index 5a992339b..aad2398d8 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -77,9 +77,9 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){
 
 UHD_STATIC_BLOCK(reg_basic_and_lf_dboards){
     dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX");
-    dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("ab")("a")("b"));
+    dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("AB")("A")("B"));
     dboard_manager::register_dboard(0x000e, &make_lf_tx,    "LF TX");
-    dboard_manager::register_dboard(0x000f, &make_lf_rx,    "LF RX",    list_of("ab")("a")("b"));
+    dboard_manager::register_dboard(0x000f, &make_lf_rx,    "LF RX",    list_of("AB")("A")("B"));
 }
 
 /***********************************************************************
@@ -139,7 +139,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
         return;
 
     case SUBDEV_PROP_QUADRATURE:
-        val = (get_subdev_name() == "ab"); //only quadrature in ab mode
+        val = (get_subdev_name() == "AB"); //only quadrature in ab mode
         return;
 
     case SUBDEV_PROP_IQ_SWAPPED:
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index b86546248..3f318d3ed 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -33,6 +33,7 @@
 #include <uhd/types/ranges.hpp>
 #include <uhd/utils/assert.hpp>
 #include <uhd/utils/static.hpp>
+#include <uhd/utils/algorithm.hpp>
 #include <uhd/usrp/dboard_base.hpp>
 #include <uhd/usrp/dboard_manager.hpp>
 #include <boost/assign/list_of.hpp>
@@ -45,6 +46,8 @@ using namespace boost::assign;
 /***********************************************************************
  * The RFX series of dboards
  **********************************************************************/
+static const float _max_rx_pga0_gain = 45;
+
 class rfx_xcvr : public xcvr_dboard_base{
 public:
     rfx_xcvr(ctor_args_t const& args, const freq_range_t &freq_range);
@@ -140,7 +143,7 @@ rfx_xcvr::rfx_xcvr(
 
     //set some default values
     set_lo_freq((_freq_range.min + _freq_range.max)/2.0);
-    set_rx_ant("rx2");
+    set_rx_ant("RX2");
     set_rx_pga0_gain(0);
 }
 
@@ -152,20 +155,40 @@ rfx_xcvr::~rfx_xcvr(void){
  * Helper Methods
  **********************************************************************/
 void rfx_xcvr::set_lo_freq(double freq){
-    /* NOP */
+    //TODO !!!
     reload_adf4360_regs();
 }
 
 void rfx_xcvr::set_rx_ant(const std::string &ant){
+    //validate input
+    ASSERT_THROW(ant == "TX/RX" or ant == "RX2");
+
     //set the rx atr regs that change with antenna setting
     this->get_iface()->set_atr_reg(
         dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY,
-        POWER_UP | MIX_EN | ((ant == "tx/rx")? ANT_TXRX : ANT_RX2)
+        POWER_UP | MIX_EN | ((ant == "TX/RX")? ANT_TXRX : ANT_RX2)
     );
+
+    //shadow the setting
+    _rx_ant = ant;
 }
 
 void rfx_xcvr::set_rx_pga0_gain(float gain){
-    /* NOP */
+    //clip the input
+    gain = std::clip(gain, 0, _max_rx_pga0_gain);
+
+    //voltage level constants
+    static const float max_volts = .2, min_volts = 1.2;
+    static const float slope = (max_volts-min_volts)/_max_rx_pga0_gain;
+
+    //calculate the voltage for the aux dac
+    float dac_volts = gain*slope + min_volts;
+
+    //write the new voltage to the aux dac
+    this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, 1, dac_volts);
+
+    //shadow the setting (does not account for precision loss)
+    _rx_pga0_gain = gain;
 }
 
 void rfx_xcvr::reload_adf4360_regs(void){
@@ -201,15 +224,17 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
         return;
 
     case SUBDEV_PROP_GAIN:
+        ASSERT_THROW(name == "PGA0");
         val = _rx_pga0_gain;
         return;
 
     case SUBDEV_PROP_GAIN_RANGE:
-        val = gain_range_t(0, 45, float(0.022));
+        ASSERT_THROW(name == "PGA0");
+        val = gain_range_t(0, _max_rx_pga0_gain, float(0.022));
         return;
 
     case SUBDEV_PROP_GAIN_NAMES:
-        val = prop_names_t(1, "pga0");
+        val = prop_names_t(1, "PGA0");
         return;
 
     case SUBDEV_PROP_FREQ:
@@ -225,7 +250,7 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
         return;
 
     case SUBDEV_PROP_ANTENNA_NAMES:{
-            prop_names_t ants = list_of("tx/rx")("rx2");
+            prop_names_t ants = list_of("TX/RX")("RX2");
             val = ants;
         }
         return;
@@ -256,7 +281,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
     switch(key.as<subdev_prop_t>()){
 
     case SUBDEV_PROP_GAIN:
-        ASSERT_THROW(name == "pga0");
+        ASSERT_THROW(name == "PGA0");
         set_rx_pga0_gain(val.as<float>());
         return;
 
@@ -309,11 +334,11 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
         return;
 
     case SUBDEV_PROP_ANTENNA:
-        val = std::string("tx/rx");
+        val = std::string("TX/RX");
         return;
 
     case SUBDEV_PROP_ANTENNA_NAMES:
-        val = prop_names_t(1, "tx/rx");
+        val = prop_names_t(1, "TX/RX");
         return;
 
     case SUBDEV_PROP_QUADRATURE:
@@ -347,7 +372,7 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
 
     case SUBDEV_PROP_ANTENNA:
         //its always set to tx/rx, so we only allow this value
-        ASSERT_THROW(val.as<std::string>() == "tx/rx");
+        ASSERT_THROW(val.as<std::string>() == "TX/RX");
         return;
 
     default:
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index f77dfc495..2859a7981 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -22,6 +22,7 @@
 #include <uhd/utils/assert.hpp>
 #include <boost/assign/list_of.hpp>
 #include <boost/asio.hpp> //htonl and ntohl
+#include <boost/math/special_functions/round.hpp>
 #include <algorithm>
 
 using namespace uhd::usrp;
@@ -31,8 +32,8 @@ public:
     usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl);
     ~usrp2_dboard_iface(void);
 
-    void write_aux_dac(unit_t, int, int);
-    int read_aux_adc(unit_t, int);
+    void write_aux_dac(unit_t, int, float);
+    float read_aux_adc(unit_t, int);
 
     void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
     void set_gpio_ddr(unit_t, boost::uint16_t);
@@ -251,20 +252,20 @@ static boost::uint8_t unit_to_otw(dboard_iface::unit_t unit){
     throw std::invalid_argument("unknown unit type");
 }
 
-void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, int value){
+void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, float value){
     //setup the out data
     usrp2_ctrl_data_t out_data;
     out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO);
     out_data.data.aux_args.dir = unit_to_otw(unit);
     out_data.data.aux_args.which = which;
-    out_data.data.aux_args.value = htonl(value);
+    out_data.data.aux_args.value = htonl(boost::math::iround(4095*value/3.3));
 
     //send and recv
     usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
     ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE);
 }
 
-int usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){
+float usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){
     //setup the out data
     usrp2_ctrl_data_t out_data;
     out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO);
@@ -274,5 +275,5 @@ int usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){
     //send and recv
     usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
     ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE);
-    return ntohl(in_data.data.aux_args.value);
+    return float(3.3*ntohl(in_data.data.aux_args.value)/4095);
 }
-- 
cgit v1.2.3