aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshish Chaudhari <ashish@ettus.com>2015-01-22 14:15:34 -0800
committerAshish Chaudhari <ashish@ettus.com>2015-01-22 14:15:34 -0800
commit1f44f06abad589d2244eecfcbca1618b4fcb3ffd (patch)
treeace8223ec045ab7d53a383d5e4805aa5deb00a80
parent9c3cdb6ee831f164e5a8734a71ad3cd5543719ac (diff)
downloaduhd-1f44f06abad589d2244eecfcbca1618b4fcb3ffd.tar.gz
uhd-1f44f06abad589d2244eecfcbca1618b4fcb3ffd.tar.bz2
uhd-1f44f06abad589d2244eecfcbca1618b4fcb3ffd.zip
e300: UHD support for refclk disciplining using PPS.
- Only supported value for clk_source is internal - time_source automatically changes the disciplining pulse source - Added ref_locked sensor
-rw-r--r--host/docs/usrp_e3x0.dox7
-rw-r--r--host/lib/usrp/e300/e300_impl.cpp23
-rw-r--r--host/lib/usrp/e300/e300_network.cpp2
-rw-r--r--host/lib/usrp/e300/e300_sensor_manager.cpp69
-rw-r--r--host/lib/usrp/e300/e300_sensor_manager.hpp6
5 files changed, 87 insertions, 20 deletions
diff --git a/host/docs/usrp_e3x0.dox b/host/docs/usrp_e3x0.dox
index 7fab73f20..8f94ea64d 100644
--- a/host/docs/usrp_e3x0.dox
+++ b/host/docs/usrp_e3x0.dox
@@ -7,7 +7,6 @@
- Hardware Capabilities:
Integrated RF frontend (70 MHz - 6 GHz)
- External PPS reference input
- - External 10 MHz reference input
- Configurable clock rate
- Internal GPIO connector with UHD API control
- 2 USB 2.0 Host ports
@@ -132,7 +131,7 @@ which should return 'arm-oe-linux-gnueabi'.
-# Setup your environment as described in \ref e3x0_sdk_usage
-# Type the following in the build directory (assuming a build in host/build):
- $ cmake -DCMAKE_TOOLCHAIN_FILE=<youruhdsrc>/host/cmake/Toolchains/oe-sdk_cross.cmake -DENABLE_E300 ..
+ $ cmake -DCMAKE_TOOLCHAIN_FILE=<youruhdsrc>/host/cmake/Toolchains/oe-sdk_cross.cmake -DENABLE_E300=ON ..
$ make
\subsubsection e3x0_sdk_usage_gnuradio Building GNU Radio
@@ -276,6 +275,8 @@ You may need to change the USRP's IP address for several reasons:
\subsection e3x0_hw_pps PPS - Pulse Per Second
Using a PPS signal for timestamp synchronization requires a square wave signal with the following a 5Vpp amplitude.
+An external PPS can be used to discipline the internal reference clock. This feature is automatically
+enabled with the time source is set to "external".
To test the PPS input, you can use the following tool from the UHD examples:
@@ -288,6 +289,8 @@ To test the PPS input, you can use the following tool from the UHD examples:
Your USRP-E Series device comes with an internal GPS.
In order to get a lock on a satellite an external GPS antenna is required.
+The PPS from the internal GPS can be used to discipline the internal reference clock. This feature is automatically
+enabled with the time source is set to "gpsdo".
The device provides a 3.3V supply voltage to an external antenna connected to the *GPS* port
of your device. Note that this supply voltage is turned off in order to safe power upon destruction of the software object.
diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp
index d04794947..c74ce9412 100644
--- a/host/lib/usrp/e300/e300_impl.cpp
+++ b/host/lib/usrp/e300/e300_impl.cpp
@@ -381,7 +381,7 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)
} catch (std::exception &e) {
UHD_MSG(error) << "An error occured making GPSDO control: " << e.what() << std::endl;
}
- _sensor_manager = e300_sensor_manager::make_local(_gps);
+ _sensor_manager = e300_sensor_manager::make_local(_gps, _global_regs);
}
UHD_MSG(status) << (_sensor_manager->get_gps_found() ? "found" : "not found") << std::endl;
@@ -493,14 +493,15 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)
.subscribe(boost::bind(&time_core_3000::set_time_next_pps, _radio_perifs[1].time64, _1));
//setup time source props
_tree->create<std::string>(mb_path / "time_source" / "value")
- .subscribe(boost::bind(&e300_impl::_update_time_source, this, _1));
- static const std::vector<std::string> time_sources = boost::assign::list_of("none")("external")("gpsdo");
+ .subscribe(boost::bind(&e300_impl::_update_time_source, this, _1))
+ .set("internal");
+ static const std::vector<std::string> time_sources = boost::assign::list_of("none")("internal")("external")("gpsdo");
_tree->create<std::vector<std::string> >(mb_path / "time_source" / "options").set(time_sources);
//setup reference source props
_tree->create<std::string>(mb_path / "clock_source" / "value")
- .subscribe(boost::bind(&e300_impl::_update_clock_source, this, _1));
- static const std::vector<std::string> clock_sources = boost::assign::list_of("internal");
- // not implemented ("external")("gpsdo");
+ .subscribe(boost::bind(&e300_impl::_update_clock_source, this, _1))
+ .set("internal");
+ static const std::vector<std::string> clock_sources = boost::assign::list_of("internal"); //external,gpsdo not supported
_tree->create<std::vector<std::string> >(mb_path / "clock_source" / "options").set(clock_sources);
////////////////////////////////////////////////////////////////////
@@ -895,14 +896,20 @@ e300_impl::both_xports_t e300_impl::_make_transport(
return xports;
}
-void e300_impl::_update_clock_source(const std::string &)
+void e300_impl::_update_clock_source(const std::string &source)
{
+ if (source != "internal") {
+ throw uhd::value_error(boost::str(
+ boost::format("Clock source option not supported: %s. The only value supported is \"internal\". " \
+ "To discipline the internal oscillator, set the appropriate time source.") % source
+ ));
+ }
}
void e300_impl::_update_antenna_sel(const size_t &which, const std::string &ant)
{
if (ant != "TX/RX" and ant != "RX2")
- throw uhd::value_error("e300: unknown RX antenna option: " + ant);
+ throw uhd::value_error("Unknown RX antenna option: " + ant);
_radio_perifs[which].ant_rx2 = (ant == "RX2");
this->_update_atrs();
}
diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp
index 6d36d8681..a21c508fe 100644
--- a/host/lib/usrp/e300/e300_network.cpp
+++ b/host/lib/usrp/e300/e300_network.cpp
@@ -622,7 +622,7 @@ network_server_impl::network_server_impl(const uhd::device_addr_t &device_addr)
// This is horrible ... why do I have to sleep here?
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
_sensor_manager = e300_sensor_manager::make_local(
- gps::ublox::ubx::control::make("/dev/ttyPS1", 9600));
+ gps::ublox::ubx::control::make("/dev/ttyPS1", 9600), _global_regs);
}
}}} // namespace
diff --git a/host/lib/usrp/e300/e300_sensor_manager.cpp b/host/lib/usrp/e300/e300_sensor_manager.cpp
index 5e65b8fd3..95f31742b 100644
--- a/host/lib/usrp/e300/e300_sensor_manager.cpp
+++ b/host/lib/usrp/e300/e300_sensor_manager.cpp
@@ -38,7 +38,7 @@ public:
std::vector<std::string> get_sensors()
{
- return boost::assign::list_of("temp")("gps_locked")("gps_time");
+ return boost::assign::list_of("temp")("gps_locked")("gps_time")("ref_locked");
}
uhd::sensor_value_t get_sensor(const std::string &key)
@@ -49,6 +49,8 @@ public:
return get_gps_lock();
else if (key == "gps_time")
return get_gps_time();
+ else if (key == "ref_locked")
+ return get_ref_lock();
else
throw uhd::lookup_error(
str(boost::format("Invalid sensor %s requested.") % key));
@@ -194,6 +196,40 @@ public:
return sensor_value_t("GPS lock status", static_cast<bool>(uhd::ntohx(transaction.value)), "locked", "unlocked");
}
+ uhd::sensor_value_t get_ref_lock(void)
+ {
+ boost::mutex::scoped_lock(_mutex);
+ sensor_transaction_t transaction;
+ transaction.which = uhd::htonx<boost::uint32_t>(REF_LOCK);
+ {
+ uhd::transport::managed_send_buffer::sptr buff
+ = _xport->get_send_buff(1.0);
+ if (not buff or buff->size() < sizeof(transaction)) {
+ throw uhd::runtime_error("sensor proxy send timeout");
+ }
+ std::memcpy(
+ buff->cast<void *>(),
+ &transaction,
+ sizeof(transaction));
+ buff->commit(sizeof(transaction));
+ }
+ {
+ uhd::transport::managed_recv_buffer::sptr buff
+ = _xport->get_recv_buff(1.0);
+
+ if (not buff or buff->size() < sizeof(transaction))
+ throw uhd::runtime_error("sensor proxy recv timeout");
+
+ std::memcpy(
+ &transaction,
+ buff->cast<const void *>(),
+ sizeof(transaction));
+ }
+ UHD_ASSERT_THROW(uhd::ntohx<boost::uint32_t>(transaction.which) == REF_LOCK);
+ // TODO: Use proper serialization here ...
+ return sensor_value_t("Ref", static_cast<bool>(uhd::ntohx(transaction.value)), "locked", "unlocked");
+ }
+
private:
uhd::transport::zero_copy_if::sptr _xport;
boost::mutex _mutex;
@@ -219,13 +255,14 @@ static const std::string E300_TEMP_SYSFS = "iio:device0";
class e300_sensor_local : public e300_sensor_manager
{
public:
- e300_sensor_local(uhd::gps_ctrl::sptr gps_ctrl) : _gps_ctrl(gps_ctrl)
+ e300_sensor_local(uhd::gps_ctrl::sptr gps_ctrl, global_regs::sptr global_regs) :
+ _gps_ctrl(gps_ctrl), _global_regs(global_regs)
{
}
std::vector<std::string> get_sensors()
{
- return boost::assign::list_of("temp")("gps_locked")("gps_time");
+ return boost::assign::list_of("temp")("gps_locked")("gps_time")("ref_locked");
}
uhd::sensor_value_t get_sensor(const std::string &key)
@@ -236,6 +273,8 @@ public:
return get_gps_lock();
else if (key == "gps_time")
return get_gps_time();
+ else if (key == "ref_locked")
+ return get_ref_lock();
else
throw uhd::lookup_error(
str(boost::format("Invalid sensor %s requested.") % key));
@@ -267,22 +306,38 @@ public:
return _gps_ctrl->get_sensor("gps_time");
}
+ uhd::sensor_value_t get_ref_lock(void)
+ {
+ //PPSLOOP_LOCKED_MASK is asserted in the following cases:
+ //- (Time source = GPS or External) AND (Loop is locked and is in fine adj mode)
+ //- Time source is Internal
+ static const boost::uint32_t PPSLOOP_LOCKED_MASK = 0x04;
+ static const boost::uint32_t REFPLL_LOCKED_MASK = 0x20;
+
+ const boost::uint32_t status =
+ _global_regs->peek32(global_regs::RB32_CORE_MISC);
+ bool ref_locked = (status & PPSLOOP_LOCKED_MASK) && (status & REFPLL_LOCKED_MASK);
+
+ return sensor_value_t("Ref", ref_locked, "locked", "unlocked");
+ }
+
private:
- gps_ctrl::sptr _gps_ctrl;
+ gps_ctrl::sptr _gps_ctrl;
+ global_regs::sptr _global_regs;
};
}}}
using namespace uhd::usrp::e300;
e300_sensor_manager::sptr e300_sensor_manager::make_local(
- uhd::gps_ctrl::sptr gps_ctrl)
+ uhd::gps_ctrl::sptr gps_ctrl, global_regs::sptr global_regs)
{
- return sptr(new e300_sensor_local(gps_ctrl));
+ return sptr(new e300_sensor_local(gps_ctrl, global_regs));
}
#else
using namespace uhd::usrp::e300;
e300_sensor_manager::sptr e300_sensor_manager::make_local(
- uhd::gps_ctrl::sptr gps_ctrl)
+ uhd::gps_ctrl::sptr, global_regs::sptr)
{
throw uhd::assertion_error("e300_sensor_manager::make_local() !E300_NATIVE");
}
diff --git a/host/lib/usrp/e300/e300_sensor_manager.hpp b/host/lib/usrp/e300/e300_sensor_manager.hpp
index 503a7bb63..9c060b19a 100644
--- a/host/lib/usrp/e300/e300_sensor_manager.hpp
+++ b/host/lib/usrp/e300/e300_sensor_manager.hpp
@@ -22,6 +22,7 @@
#include <uhd/types/sensors.hpp>
#include <uhd/utils/byteswap.hpp>
#include <uhd/usrp/gps_ctrl.hpp>
+#include "e300_global_regs.hpp"
#ifndef INCLUDED_E300_SENSOR_MANAGER_HPP
#define INCLUDED_E300_SENSOR_MANAGER_HPP
@@ -39,7 +40,7 @@ struct sensor_transaction_t {
enum sensor {ZYNQ_TEMP=0, GPS_FOUND=1, GPS_TIME=2,
- GPS_LOCK=3};
+ GPS_LOCK=3, REF_LOCK=4};
class e300_sensor_manager : boost::noncopyable
{
@@ -53,9 +54,10 @@ public:
virtual uhd::sensor_value_t get_mb_temp(void) = 0;
virtual uhd::sensor_value_t get_gps_lock(void) = 0;
virtual uhd::sensor_value_t get_gps_time(void) = 0;
+ virtual uhd::sensor_value_t get_ref_lock(void) = 0;
static sptr make_proxy(uhd::transport::zero_copy_if::sptr xport);
- static sptr make_local(uhd::gps_ctrl::sptr gps_ctrl);
+ static sptr make_local(uhd::gps_ctrl::sptr gps_ctrl, global_regs::sptr global_regs);
// Note: This is a hack
static boost::uint32_t pack_float_in_uint32_t(const float &v)