summaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/dboard/CMakeLists.txt1
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp26
-rw-r--r--host/lib/usrp/dboard/db_unknown.cpp265
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp5
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp5
-rw-r--r--host/lib/usrp/dboard_manager.cpp58
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.cpp45
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.hpp27
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp66
-rw-r--r--host/lib/usrp/usrp2/fw_common.h8
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp2
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp2
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp4
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp6
14 files changed, 454 insertions, 66 deletions
diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt
index 3a6c2d84a..6093583d3 100644
--- a/host/lib/usrp/dboard/CMakeLists.txt
+++ b/host/lib/usrp/dboard/CMakeLists.txt
@@ -22,5 +22,6 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_rfx.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_xcvr2450.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_wbx.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_unknown.cpp
)
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 2585dfa8d..2d6088983 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -137,25 +137,21 @@ static dboard_base::sptr make_rfx_flex1200(dboard_base::ctor_args_t args){
return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1150e6, 1450e6), true, true));
}
+static dboard_base::sptr make_rfx_flex2200(dboard_base::ctor_args_t args){
+ return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(2000e6, 2400e6), false, false));
+}
+
static dboard_base::sptr make_rfx_flex2400(dboard_base::ctor_args_t args){
return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(2300e6, 2900e6), false, false));
}
UHD_STATIC_BLOCK(reg_rfx_dboards){
- dboard_manager::register_dboard(0x0024, &make_rfx_flex400, "Flex 400 Rx MIMO B");
- dboard_manager::register_dboard(0x0028, &make_rfx_flex400, "Flex 400 Tx MIMO B");
-
- dboard_manager::register_dboard(0x0025, &make_rfx_flex900, "Flex 900 Rx MIMO B");
- dboard_manager::register_dboard(0x0029, &make_rfx_flex900, "Flex 900 Tx MIMO B");
-
- dboard_manager::register_dboard(0x0034, &make_rfx_flex1800, "Flex 1800 Rx MIMO B");
- dboard_manager::register_dboard(0x0035, &make_rfx_flex1800, "Flex 1800 Tx MIMO B");
-
- dboard_manager::register_dboard(0x0026, &make_rfx_flex1200, "Flex 1200 Rx MIMO B");
- dboard_manager::register_dboard(0x002a, &make_rfx_flex1200, "Flex 1200 Tx MIMO B");
-
- dboard_manager::register_dboard(0x0027, &make_rfx_flex2400, "Flex 2400 Rx MIMO B");
- dboard_manager::register_dboard(0x002b, &make_rfx_flex2400, "Flex 2400 Tx MIMO B");
+ dboard_manager::register_dboard(0x0024, 0x0028, &make_rfx_flex400, "Flex 400 MIMO B");
+ dboard_manager::register_dboard(0x0025, 0x0029, &make_rfx_flex900, "Flex 900 MIMO B");
+ dboard_manager::register_dboard(0x0034, 0x0035, &make_rfx_flex1800, "Flex 1800 MIMO B");
+ dboard_manager::register_dboard(0x0026, 0x002a, &make_rfx_flex1200, "Flex 1200 MIMO B");
+ dboard_manager::register_dboard(0x002c, 0x002d, &make_rfx_flex2200, "Flex 2200 MIMO B");
+ dboard_manager::register_dboard(0x0027, 0x002b, &make_rfx_flex2400, "Flex 2400 MIMO B");
}
/***********************************************************************
@@ -257,7 +253,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_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp
new file mode 100644
index 000000000..ced27e34d
--- /dev/null
+++ b/host/lib/usrp/dboard/db_unknown.cpp
@@ -0,0 +1,265 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/usrp/dboard_base.hpp>
+#include <uhd/usrp/dboard_manager.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/format.hpp>
+
+using namespace uhd;
+using namespace uhd::usrp;
+using namespace boost::assign;
+
+/***********************************************************************
+ * The unknown boards:
+ * Like a basic board, but with only one subdev.
+ **********************************************************************/
+class unknown_rx : public rx_dboard_base{
+public:
+ unknown_rx(ctor_args_t args);
+ ~unknown_rx(void);
+
+ void rx_get(const wax::obj &key, wax::obj &val);
+ void rx_set(const wax::obj &key, const wax::obj &val);
+};
+
+class unknown_tx : public tx_dboard_base{
+public:
+ unknown_tx(ctor_args_t args);
+ ~unknown_tx(void);
+
+ void tx_get(const wax::obj &key, wax::obj &val);
+ void tx_set(const wax::obj &key, const wax::obj &val);
+};
+
+/***********************************************************************
+ * Register the unknown dboards
+ **********************************************************************/
+static dboard_base::sptr make_unknown_rx(dboard_base::ctor_args_t args){
+ return dboard_base::sptr(new unknown_rx(args));
+}
+
+static dboard_base::sptr make_unknown_tx(dboard_base::ctor_args_t args){
+ return dboard_base::sptr(new unknown_tx(args));
+}
+
+UHD_STATIC_BLOCK(reg_unknown_dboards){
+ dboard_manager::register_dboard(0xfff0, &make_unknown_tx, "Unknown TX");
+ dboard_manager::register_dboard(0xfff1, &make_unknown_rx, "Unknown RX");
+}
+
+/***********************************************************************
+ * Unknown RX dboard
+ **********************************************************************/
+unknown_rx::unknown_rx(ctor_args_t args) : rx_dboard_base(args){
+ /* NOP */
+}
+
+unknown_rx::~unknown_rx(void){
+ /* NOP */
+}
+
+void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_NAME:
+ val = "Unknown - " + get_rx_id().to_pp_string();
+ return;
+
+ case SUBDEV_PROP_OTHERS:
+ val = prop_names_t(); //empty
+ return;
+
+ case SUBDEV_PROP_GAIN:
+ val = float(0);
+ return;
+
+ case SUBDEV_PROP_GAIN_RANGE:
+ val = gain_range_t(0, 0, 0);
+ return;
+
+ case SUBDEV_PROP_GAIN_NAMES:
+ val = prop_names_t(); //empty
+ return;
+
+ case SUBDEV_PROP_FREQ:
+ val = double(0);
+ return;
+
+ case SUBDEV_PROP_FREQ_RANGE:
+ val = freq_range_t(0, 0);
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ val = std::string("");
+ return;
+
+ case SUBDEV_PROP_ANTENNA_NAMES:
+ val = prop_names_t(1, ""); //vector of 1 empty string
+ return;
+
+ case SUBDEV_PROP_QUADRATURE:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_IQ_SWAPPED:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_SPECTRUM_INVERTED:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_LO_LOCKED:
+ val = true; //there is no LO, so it must be true!
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_GAIN:
+ UHD_ASSERT_THROW(val.as<float>() == float(0));
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ UHD_ASSERT_THROW(val.as<std::string>() == std::string(""));
+ return;
+
+ case SUBDEV_PROP_FREQ:
+ return; // it wont do you much good, but you can set it
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
+
+/***********************************************************************
+ * Basic and LF TX dboard
+ **********************************************************************/
+unknown_tx::unknown_tx(ctor_args_t args) : tx_dboard_base(args){
+ /* NOP */
+}
+
+unknown_tx::~unknown_tx(void){
+ /* NOP */
+}
+
+void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_NAME:
+ val = "Unknown - " + get_tx_id().to_pp_string();
+ return;
+
+ case SUBDEV_PROP_OTHERS:
+ val = prop_names_t(); //empty
+ return;
+
+ case SUBDEV_PROP_GAIN:
+ val = float(0);
+ return;
+
+ case SUBDEV_PROP_GAIN_RANGE:
+ val = gain_range_t(0, 0, 0);
+ return;
+
+ case SUBDEV_PROP_GAIN_NAMES:
+ val = prop_names_t(); //empty
+ return;
+
+ case SUBDEV_PROP_FREQ:
+ val = double(0);
+ return;
+
+ case SUBDEV_PROP_FREQ_RANGE:
+ val = freq_range_t(0, 0);
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ val = std::string("");
+ return;
+
+ case SUBDEV_PROP_ANTENNA_NAMES:
+ val = prop_names_t(1, ""); //vector of 1 empty string
+ return;
+
+ case SUBDEV_PROP_QUADRATURE:
+ val = true;
+ return;
+
+ case SUBDEV_PROP_IQ_SWAPPED:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_SPECTRUM_INVERTED:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_LO_LOCKED:
+ val = true; //there is no LO, so it must be true!
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_GAIN:
+ UHD_ASSERT_THROW(val.as<float>() == float(0));
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ UHD_ASSERT_THROW(val.as<std::string>() == std::string(""));
+ return;
+
+ case SUBDEV_PROP_FREQ:
+ return; // it wont do you much good, but you can set it
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index 95dcb3802..2b2822b6b 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -154,8 +154,7 @@ static dboard_base::sptr make_wbx(dboard_base::ctor_args_t args){
}
UHD_STATIC_BLOCK(reg_wbx_dboards){
- dboard_manager::register_dboard(0x0052, &make_wbx, "WBX RX");
- dboard_manager::register_dboard(0x0053, &make_wbx, "WBX TX");
+ dboard_manager::register_dboard(0x0052, 0x0053, &make_wbx, "WBX");
}
/***********************************************************************
@@ -246,7 +245,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..5032b6f31 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);
}
};
@@ -158,8 +158,7 @@ static dboard_base::sptr make_xcvr2450(dboard_base::ctor_args_t args){
UHD_STATIC_BLOCK(reg_xcvr2450_dboard){
//register the factory function for the rx and tx dbids
- dboard_manager::register_dboard(0x0060, &make_xcvr2450, "XCVR2450 TX");
- dboard_manager::register_dboard(0x0061, &make_xcvr2450, "XCVR2450 RX");
+ dboard_manager::register_dboard(0x0061, 0x0060, &make_xcvr2450, "XCVR2450");
}
/***********************************************************************
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index 35ddfc4ee..6321e018f 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -43,7 +43,7 @@ typedef uhd::dict<dboard_id_t, args_t> id_to_args_map_t;
UHD_SINGLETON_FCN(id_to_args_map_t, get_id_to_args_map)
void dboard_manager::register_dboard(
- dboard_id_t dboard_id,
+ const dboard_id_t &dboard_id,
dboard_ctor_t dboard_ctor,
const std::string &name,
const prop_names_t &subdev_names
@@ -57,6 +57,26 @@ void dboard_manager::register_dboard(
get_id_to_args_map()[dboard_id] = args_t(dboard_ctor, name, subdev_names);
}
+//map an xcvr dboard id to its partner dboard id
+typedef uhd::dict<dboard_id_t, dboard_id_t> xcvr_id_to_id_map_t;
+UHD_SINGLETON_FCN(xcvr_id_to_id_map_t, get_xcvr_id_to_id_map)
+
+void dboard_manager::register_dboard(
+ const dboard_id_t &rx_dboard_id,
+ const dboard_id_t &tx_dboard_id,
+ dboard_ctor_t dboard_ctor,
+ const std::string &name,
+ const prop_names_t &subdev_names
+){
+ //regular registration for ids
+ register_dboard(rx_dboard_id, dboard_ctor, name + " RX", subdev_names);
+ register_dboard(tx_dboard_id, dboard_ctor, name + " TX", subdev_names);
+
+ //register xcvr mapping for ids
+ get_xcvr_id_to_id_map()[rx_dboard_id] = tx_dboard_id;
+ get_xcvr_id_to_id_map()[tx_dboard_id] = rx_dboard_id;
+}
+
std::string dboard_id_t::to_pp_string(void) const{
std::string name = "unknown";
if (get_id_to_args_map().has_key(*this)){
@@ -168,26 +188,27 @@ dboard_manager::sptr dboard_manager::make(
**********************************************************************/
static args_t get_dboard_args(
dboard_iface::unit_t unit,
- dboard_id_t dboard_id
+ dboard_id_t dboard_id,
+ bool force_to_unknown = false
){
//special case, the none id was provided, use the following ids
- if (dboard_id == dboard_id_t::none()){
+ if (dboard_id == dboard_id_t::none() or force_to_unknown){
std::cerr << boost::format(
- "Warning: unregistered dboard id: %s"
- " -> defaulting to a basic board"
+ "Warning: unknown dboard-id or dboard-id combination: %s\n"
+ " -> defaulting to the unknown board type"
) % dboard_id.to_pp_string() << std::endl;
- UHD_ASSERT_THROW(get_id_to_args_map().has_key(0x0001));
- UHD_ASSERT_THROW(get_id_to_args_map().has_key(0x0000));
+ UHD_ASSERT_THROW(get_id_to_args_map().has_key(0xfff1));
+ UHD_ASSERT_THROW(get_id_to_args_map().has_key(0xfff0));
switch(unit){
- case dboard_iface::UNIT_RX: return get_dboard_args(unit, 0x0001);
- case dboard_iface::UNIT_TX: return get_dboard_args(unit, 0x0000);
+ case dboard_iface::UNIT_RX: return get_dboard_args(unit, 0xfff1);
+ case dboard_iface::UNIT_TX: return get_dboard_args(unit, 0xfff0);
default: UHD_THROW_INVALID_CODE_PATH();
}
}
//verify that there is a registered constructor for this id
if (not get_id_to_args_map().has_key(dboard_id)){
- return get_dboard_args(unit, dboard_id_t::none());
+ return get_dboard_args(unit, dboard_id, true);
}
//return the dboard args for this id
@@ -201,11 +222,21 @@ dboard_manager_impl::dboard_manager_impl(
){
_iface = iface;
+ //determine xcvr status
+ bool rx_dboard_is_xcvr = get_xcvr_id_to_id_map().has_key(rx_dboard_id);
+ bool tx_dboard_is_xcvr = get_xcvr_id_to_id_map().has_key(tx_dboard_id);
+ bool this_dboard_is_xcvr = (
+ rx_dboard_is_xcvr and tx_dboard_is_xcvr and
+ (get_xcvr_id_to_id_map()[rx_dboard_id] == tx_dboard_id) and
+ (get_xcvr_id_to_id_map()[tx_dboard_id] == rx_dboard_id)
+ );
+
+ //extract dboard constructor and settings (force to unknown for messed up xcvr status)
dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs;
- boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(dboard_iface::UNIT_RX, rx_dboard_id);
+ boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(dboard_iface::UNIT_RX, rx_dboard_id, rx_dboard_is_xcvr != this_dboard_is_xcvr);
dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs;
- boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(dboard_iface::UNIT_TX, tx_dboard_id);
+ boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(dboard_iface::UNIT_TX, tx_dboard_id, tx_dboard_is_xcvr != this_dboard_is_xcvr);
//initialize the gpio pins before creating subdevs
set_nice_dboard_if();
@@ -215,7 +246,8 @@ dboard_manager_impl::dboard_manager_impl(
db_ctor_args.db_iface = iface;
//make xcvr subdevs (make one subdev for both rx and tx dboards)
- if (rx_dboard_ctor == tx_dboard_ctor){
+ if (this_dboard_is_xcvr){
+ UHD_ASSERT_THROW(rx_dboard_ctor == tx_dboard_ctor);
UHD_ASSERT_THROW(rx_subdevs == tx_subdevs);
BOOST_FOREACH(const std::string &subdev, rx_subdevs){
db_ctor_args.sd_name = subdev;
diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp
index d9baa66cf..b9be037c0 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;
@@ -79,23 +80,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..6f2fb9396 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -21,6 +21,7 @@
#include <uhd/usrp/dboard_iface.hpp>
#include <uhd/types/dict.hpp>
#include <uhd/utils/assert.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/asio.hpp> //htonl and ntohl
#include <boost/math/special_functions/round.hpp>
@@ -36,8 +37,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 +49,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 +75,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);
};
@@ -107,6 +110,10 @@ usrp2_dboard_iface::usrp2_dboard_iface(
_dac_regs[unit].cmd = ad5623_regs_t::CMD_RESET;
this->_write_aux_dac(unit);
}
+
+ //init the clock rate shadows with max rate clock
+ this->set_clock_rate(UNIT_RX, sorted(this->get_clock_rates(UNIT_RX)).back());
+ this->set_clock_rate(UNIT_TX, sorted(this->get_clock_rates(UNIT_TX)).back());
}
usrp2_dboard_iface::~usrp2_dboard_iface(void){
@@ -116,8 +123,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 +263,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 +299,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(
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 75f5b1779..242d268ec 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -32,9 +32,13 @@ extern "C" {
#define _SINS_
#endif
+// define limits on bytes per udp packet
+#define USRP2_MTU_BYTES 1500
+#define USRP2_UDP_BYTES ((USRP2_MTU_BYTES) - (2 + 14 + 20 + 8)) //size of headers (pad, eth, ip, udp)
+
//defines the protocol version in this shared header
//increment this value when the protocol is changed
-#define USRP2_PROTO_VERSION 3
+#define USRP2_PROTO_VERSION 4
//used to differentiate control packets over data port
#define USRP2_INVALID_VRT_HEADER 0
@@ -102,7 +106,7 @@ typedef struct{
struct {
_SINS_ uint8_t addr;
_SINS_ uint8_t bytes;
- _SINS_ uint8_t data[sizeof(_SINS_ uint32_t)];
+ _SINS_ uint8_t data[20];
} i2c_args;
struct {
_SINS_ uint32_t addr;
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 6cb2a735b..aa0f63321 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -18,6 +18,7 @@
#include "../../transport/vrt_packet_handler.hpp"
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
+#include <uhd/utils/thread_priority.hpp>
#include <uhd/transport/convert_types.hpp>
#include <uhd/transport/bounded_buffer.hpp>
#include <boost/format.hpp>
@@ -78,6 +79,7 @@ managed_recv_buffer::sptr usrp2_impl::io_impl::get_recv_buff(void){
}
void usrp2_impl::io_impl::recv_pirate_loop(zero_copy_if::sptr zc_if){
+ set_thread_priority_safe();
recv_pirate_running = true;
while(recv_pirate_running){
managed_recv_buffer::sptr buff = zc_if->get_recv_buff();
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 6e0d3266a..83e98904e 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -146,7 +146,7 @@ public:
_ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t)));
//loop until we get the packet or timeout
- boost::uint8_t usrp2_ctrl_data_in_mem[1500]; //allocate MTU bytes for recv
+ boost::uint8_t usrp2_ctrl_data_in_mem[USRP2_UDP_BYTES]; //allocate max bytes for recv
usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem);
while(true){
size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem));
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 0837f4ac4..36c264c3c 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -79,12 +79,12 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){
udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out)));
//loop and recieve until the timeout
- boost::uint8_t usrp2_ctrl_data_in_mem[1500]; //allocate MTU bytes for recv
+ boost::uint8_t usrp2_ctrl_data_in_mem[USRP2_UDP_BYTES]; //allocate max bytes for recv
usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem);
while(true){
size_t len = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem));
//std::cout << len << "\n";
- if (len >= sizeof(usrp2_ctrl_data_t)){
+ if (len > offsetof(usrp2_ctrl_data_t, data)){
//handle the received data
switch(ntohl(ctrl_data_in->id)){
case USRP2_CTRL_ID_WAZZUP_DUDE:
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index ccc09003e..2126b9565 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -141,15 +141,13 @@ private:
/*******************************************************************
* Deal with the rx and tx packet sizes
******************************************************************/
- static const size_t _mtu = 1500; //FIXME we have no idea
- static const size_t _hdrs = (2 + 14 + 20 + 8); //size of headers (pad, eth, ip, udp)
static const size_t _max_rx_bytes_per_packet =
- _mtu - _hdrs -
+ USRP2_UDP_BYTES -
USRP2_HOST_RX_VRT_HEADER_WORDS32*sizeof(boost::uint32_t) -
USRP2_HOST_RX_VRT_TRAILER_WORDS32*sizeof(boost::uint32_t)
;
static const size_t _max_tx_bytes_per_packet =
- _mtu - _hdrs -
+ USRP2_UDP_BYTES -
uhd::transport::vrt::max_header_words32*sizeof(boost::uint32_t)
;