aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMoritz Fischer <moritz.fischer@ettus.com>2015-04-16 16:12:40 -0500
committerMartin Braun <martin.braun@ettus.com>2015-07-29 18:13:45 -0700
commit1cac345b5c7b6d576da87dc321af4223d515df51 (patch)
tree0da09b7bde4e215674c8c31c4b5a0c4830811034
parent463fc8985e29d12e2edba25008e7c0def5ce60cd (diff)
downloaduhd-1cac345b5c7b6d576da87dc321af4223d515df51.tar.gz
uhd-1cac345b5c7b6d576da87dc321af4223d515df51.tar.bz2
uhd-1cac345b5c7b6d576da87dc321af4223d515df51.zip
gps: gpsd: Adding gpsd_iface to interface with gpsd.
The gpsd_iface class might be useful for more than just e3x0, it therefore belongs into lib/usrp instead of lib/usrp/e300. A new UHD component is being registered, to cope with the additional dependency. If libgps is not found, UHD and E300 will be compiled without GPS support. This has several consequences: - The E310 GPSDO should now work transparently over network - Users can use the GPS through gpsd for other applications *while* running UHD applications - We now have a dependency on libgps We need currently at least version 3.11 (while running 3.14), on the device. Older versions do work if 3.10 runs on both sides e.g Reviewed-by: Martin Braun <martin.braun@ettus.com> Reviewed-by: Ashish Chaudhari <ashish.chaudhari@ettus.com> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
-rw-r--r--host/cmake/Modules/FindGPSD.cmake62
-rw-r--r--host/lib/usrp/CMakeLists.txt13
-rw-r--r--host/lib/usrp/e300/CMakeLists.txt12
-rw-r--r--host/lib/usrp/e300/e300_async_serial.cpp245
-rw-r--r--host/lib/usrp/e300/e300_async_serial.hpp113
-rw-r--r--host/lib/usrp/e300/e300_impl.cpp70
-rw-r--r--host/lib/usrp/e300/e300_impl.hpp11
-rw-r--r--host/lib/usrp/e300/e300_network.cpp13
-rw-r--r--host/lib/usrp/e300/e300_sensor_manager.cpp141
-rw-r--r--host/lib/usrp/e300/e300_sensor_manager.hpp9
-rw-r--r--host/lib/usrp/e300/e300_ublox_control.hpp50
-rw-r--r--host/lib/usrp/e300/e300_ublox_control_impl.cpp505
-rw-r--r--host/lib/usrp/e300/e300_ublox_control_impl.hpp457
-rw-r--r--host/lib/usrp/gpsd_iface.cpp184
-rw-r--r--host/lib/usrp/gpsd_iface.hpp36
15 files changed, 381 insertions, 1540 deletions
diff --git a/host/cmake/Modules/FindGPSD.cmake b/host/cmake/Modules/FindGPSD.cmake
new file mode 100644
index 000000000..0d56a5380
--- /dev/null
+++ b/host/cmake/Modules/FindGPSD.cmake
@@ -0,0 +1,62 @@
+#
+# Copyright 2015 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/>.
+#
+# - Find libgps
+# Find the Gpsd includes and client library
+# This module defines
+# LIBGPS_INCLUDE_DIR, where to find gps.h
+# LIBGPS_LIBRARIES, the libraries needed by a GPSD client.
+# LIBGPS_FOUND, If false, do not try to use GPSD.
+# also defined, but not for general use are
+# LIBGPS_LIBRARY, where to find the GPSD library.
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_GPSD "libgps")
+PKG_CHECK_MODULES(PC_GPSD_V3_11 "libgps > 3.11")
+
+IF(PC_GPSD_FOUND AND NOT PC_GPSD_V3_11_FOUND)
+ MESSAGE(WARNING "GPSD version found is too old")
+ENDIF(PC_GPSD_FOUND AND NOT PC_GPSD_V3_11_FOUND)
+
+IF(PC_GPSD_V3_11_FOUND)
+ FIND_PATH(
+ LIBGPS_INCLUDE_DIR
+ NAMES gps.h
+ HINTS ${PC_GPSD_INCLUDE_DIR}
+ )
+
+ SET(
+ LIBGPS_NAMES
+ ${LIBGPS_NAMES} gps
+ )
+
+ FIND_LIBRARY(
+ LIBGPS_LIBRARY
+ NAMES ${LIBGPS_NAMES}
+ HINTS ${PC_GPSD_LIBDIR}
+ )
+ENDIF(PC_GPSD_V3_11_FOUND)
+
+# handle the QUIETLY and REQUIRED arguments and set LIBGPS_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGPS DEFAULT_MSG LIBGPS_LIBRARY LIBGPS_INCLUDE_DIR)
+
+IF(LIBGPS_FOUND)
+ SET(LIBGPS_LIBRARIES ${LIBGPS_LIBRARY})
+ENDIF(LIBGPS_FOUND)
+
+MARK_AS_ADVANCED(LIBGPS_LIBRARY LIBGPS_INCLUDE_DIR)
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index f6788b5ef..ce913aaf6 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -18,6 +18,10 @@
########################################################################
# This file included, use CMake directory variables
########################################################################
+find_package(GPSD)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/dboard_base.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dboard_eeprom.cpp
@@ -30,6 +34,15 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/subdev_spec.cpp
)
+LIBUHD_REGISTER_COMPONENT("GPSD" ENABLE_GPSD OFF "ENABLE_LIBUHD;ENABLE_GPSD;LIBGPS_FOUND" OFF)
+
+IF(ENABLE_GPSD)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gpsd_iface.cpp
+ )
+ LIBUHD_APPEND_LIBS(${LIBGPS_LIBRARY})
+ENDIF(ENABLE_GPSD)
+
INCLUDE_SUBDIRECTORY(cores)
INCLUDE_SUBDIRECTORY(dboard)
INCLUDE_SUBDIRECTORY(common)
diff --git a/host/lib/usrp/e300/CMakeLists.txt b/host/lib/usrp/e300/CMakeLists.txt
index 9ee9b5521..26e34294a 100644
--- a/host/lib/usrp/e300/CMakeLists.txt
+++ b/host/lib/usrp/e300/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2013-2014 Ettus Research LLC
+# Copyright 2013-2015 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
@@ -39,8 +39,6 @@ IF(ENABLE_E300)
${CMAKE_CURRENT_SOURCE_DIR}/e300_i2c.cpp
${CMAKE_CURRENT_SOURCE_DIR}/e300_eeprom_manager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/e300_common.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/e300_async_serial.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/e300_ublox_control_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/e300_remote_codec_ctrl.cpp
)
LIBUHD_APPEND_SOURCES(${E300_SOURCES})
@@ -52,4 +50,12 @@ IF(ENABLE_E300)
PROPERTIES COMPILE_DEFINITIONS "E300_NATIVE=1"
)
ENDIF(UDEV_FOUND)
+
+ IF(ENABLE_GPSD)
+ SET_SOURCE_FILES_PROPERTIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/e300_impl.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/e300_impl.hpp
+ PROPERTIES COMPILE_DEFINITIONS "E300_GPSD=1"
+ )
+ ENDIF(ENABLE_GPSD)
ENDIF(ENABLE_E300)
diff --git a/host/lib/usrp/e300/e300_async_serial.cpp b/host/lib/usrp/e300/e300_async_serial.cpp
deleted file mode 100644
index cdf18f7f7..000000000
--- a/host/lib/usrp/e300/e300_async_serial.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-//
-// Copyright 2014 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 "e300_async_serial.hpp"
-
-namespace uhd { namespace usrp { namespace gps {
-
-async_serial::async_serial()
- : _io(),
- _port(_io),
- _background_thread(),
- _open(false),
- _error(false)
-{
-}
-
-async_serial::async_serial(
- const std::string &node,
- const size_t baud_rate,
- boost::asio::serial_port_base::parity opt_parity,
- boost::asio::serial_port_base::character_size opt_csize,
- boost::asio::serial_port_base::flow_control opt_flow,
- boost::asio::serial_port_base::stop_bits opt_stop)
- : _io(),
- _port(_io),
- _background_thread(),
- _open(false),
- _error(false)
-{
- open(node, baud_rate, opt_parity, opt_csize, opt_flow, opt_stop);
-}
-
-void async_serial::open(
- const std::string &node,
- const size_t baud_rate,
- boost::asio::serial_port_base::parity opt_parity,
- boost::asio::serial_port_base::character_size opt_csize,
- boost::asio::serial_port_base::flow_control opt_flow,
- boost::asio::serial_port_base::stop_bits opt_stop)
-{
- if(is_open())
- close();
-
- _set_error_status(true);
- _port.open(node);
- _port.set_option(
- boost::asio::serial_port_base::baud_rate(baud_rate));
- _port.set_option(opt_parity);
- _port.set_option(opt_csize);
- _port.set_option(opt_flow);
- _port.set_option(opt_stop);
-
- _io.post(boost::bind(&async_serial::_do_read, this));
-
- boost::thread t(boost::bind(&boost::asio::io_service::run, &_io));
- _background_thread.swap(t);
- _set_error_status(false);
- _open=true;
-}
-
-bool async_serial::is_open() const
-{
- return _open;
-}
-
-bool async_serial::error_status() const
-{
- boost::lock_guard<boost::mutex> l(_error_mutex);
- return _error;
-}
-
-void async_serial::close()
-{
- if(!is_open())
- return;
-
- _open=false;
- _io.post(boost::bind(&async_serial::_do_close, this));
- _background_thread.join();
- _io.reset();
- if(error_status())
- throw(boost::system::system_error(boost::system::error_code(),
- "Error while closing the device"));
-}
-
-void async_serial::write(const char *data, size_t size)
-{
- {
- boost::lock_guard<boost::mutex> l(_write_queue_mutex);
- _write_queue.insert(_write_queue.end(), data, data+size);
- }
- _io.post(boost::bind(&async_serial::_do_write, this));
-}
-
-void async_serial::write(const std::vector<char> &data)
-{
- {
- boost::lock_guard<boost::mutex> l(_write_queue_mutex);
- _write_queue.insert(
- _write_queue.end(),
- data.begin(),
- data.end());
- }
- _io.post(boost::bind(&async_serial::_do_write, this));
-}
-
-void async_serial::write_string(const std::string &s)
-{
- {
- boost::lock_guard<boost::mutex> l(_write_queue_mutex);
- _write_queue.insert(
- _write_queue.end(),
- s.begin(),
- s.end());
- }
- _io.post(boost::bind(&async_serial::_do_write, this));
-}
-
-async_serial::~async_serial()
-{
- if(is_open()) {
- try {
- close();
- } catch(...) {
- //Don't throw from a destructor
- }
- }
-}
-
-void async_serial::_do_read()
-{
- _port.async_read_some(boost::asio::buffer(
- _read_buffer,READ_BUFFER_SIZE),
- boost::bind(&async_serial::_read_end,
- this,
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
-}
-
-void async_serial::_read_end(
- const boost::system::error_code& error,
- size_t bytes_transferred)
-{
- if(error) {
- if(is_open()) {
- _do_close();
- _set_error_status(true);
- }
- } else {
- if(_callback)
- _callback(
- _read_buffer,
- bytes_transferred);
- _do_read();
- }
-}
-
-void async_serial::_do_write()
-{
- // if a write operation is already in progress, do nothing
- if(_write_buffer == 0) {
- boost::lock_guard<boost::mutex> l(_write_queue_mutex);
- _write_buffer_size=_write_queue.size();
- _write_buffer.reset(new char[_write_queue.size()]);
- std::copy(_write_queue.begin(),_write_queue.end(),
- _write_buffer.get());
- _write_queue.clear();
- async_write(
- _port, boost::asio::buffer(_write_buffer.get(),
- _write_buffer_size),
- boost::bind(
- &async_serial::_write_end,
- this,
- boost::asio::placeholders::error));
- }
-}
-
-void async_serial::_write_end(const boost::system::error_code& error)
-{
- if(!error) {
- boost::lock_guard<boost::mutex> l(_write_queue_mutex);
- if(_write_queue.empty()) {
- _write_buffer.reset();
- _write_buffer_size=0;
- return;
- }
- _write_buffer_size = _write_queue.size();
- _write_buffer.reset(new char[_write_queue.size()]);
- std::copy(_write_queue.begin(),_write_queue.end(),
- _write_buffer.get());
- _write_queue.clear();
- async_write(
- _port,
- boost::asio::buffer(_write_buffer.get(),
- _write_buffer_size),
- boost::bind(
- &async_serial::_write_end,
- this,
- boost::asio::placeholders::error));
- } else {
- _set_error_status(true);
- _do_close();
- }
-}
-
-void async_serial::_do_close()
-{
- boost::system::error_code ec;
- _port.cancel(ec);
- if(ec)
- _set_error_status(true);
- _port.close(ec);
- if(ec)
- _set_error_status(true);
-}
-
-void async_serial::_set_error_status(const bool e)
-{
- boost::lock_guard<boost::mutex> l(_error_mutex);
- _error = e;
-}
-
-
-void async_serial::set_read_callback(
- const boost::function<void (const char*, size_t)> &callback)
-{
- _callback = callback;
-}
-
-
-}}} // namespace
diff --git a/host/lib/usrp/e300/e300_async_serial.hpp b/host/lib/usrp/e300/e300_async_serial.hpp
deleted file mode 100644
index fafc7de3d..000000000
--- a/host/lib/usrp/e300/e300_async_serial.hpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//
-// Copyright 2013-2014 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/>.
-//
-
-#ifndef INCLUDED_ASYNC_SERIAL_HPP
-#define INCLUDED_ASYNC_SERIAL_HPP
-
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <boost/thread.hpp>
-#include <boost/utility.hpp>
-#include <boost/function.hpp>
-#include <boost/shared_array.hpp>
-
-namespace uhd { namespace usrp { namespace gps {
-
-class async_serial : private boost::noncopyable
-{
-public:
- async_serial();
- ~async_serial();
-
- async_serial(const std::string &node, const size_t baud_rate,
- boost::asio::serial_port_base::parity opt_parity=
- boost::asio::serial_port_base::parity(
- boost::asio::serial_port_base::parity::none),
- boost::asio::serial_port_base::character_size opt_csize=
- boost::asio::serial_port_base::character_size(8),
- boost::asio::serial_port_base::flow_control opt_flow=
- boost::asio::serial_port_base::flow_control(
- boost::asio::serial_port_base::flow_control::none),
- boost::asio::serial_port_base::stop_bits opt_stop=
- boost::asio::serial_port_base::stop_bits(
- boost::asio::serial_port_base::stop_bits::one));
-
- void open(const std::string& node, const size_t baud_rate,
- boost::asio::serial_port_base::parity opt_parity=
- boost::asio::serial_port_base::parity(
- boost::asio::serial_port_base::parity::none),
- boost::asio::serial_port_base::character_size opt_csize=
- boost::asio::serial_port_base::character_size(8),
- boost::asio::serial_port_base::flow_control opt_flow=
- boost::asio::serial_port_base::flow_control(
- boost::asio::serial_port_base::flow_control::none),
- boost::asio::serial_port_base::stop_bits opt_stop=
- boost::asio::serial_port_base::stop_bits(
- boost::asio::serial_port_base::stop_bits::one));
-
- bool is_open(void) const;
-
- bool error_status(void) const;
-
- void close(void);
-
- void write(const char *data, const size_t size);
- void write(const std::vector<char> &data);
-
- void write_string(const std::string &s);
-
- static const size_t READ_BUFFER_SIZE=512;
-
- void set_read_callback(
- const boost::function<void (const char*, size_t)>& callback);
-
- void clear_callback();
-
-private: // methods
- void _do_read();
-
- void _read_end(
- const boost::system::error_code &error,
- size_t bytes_transferred);
-
- void _do_write();
-
- void _write_end(const boost::system::error_code &error);
-
- void _do_close();
-
- void _set_error_status(const bool e);
-private: // members
- boost::asio::io_service _io;
- boost::asio::serial_port _port;
- boost::thread _background_thread;
- bool _open;
- bool _error;
- mutable boost::mutex _error_mutex;
-
- std::vector<char> _write_queue;
- boost::shared_array<char> _write_buffer;
- size_t _write_buffer_size;
- boost::mutex _write_queue_mutex;
- char _read_buffer[READ_BUFFER_SIZE];
-
- boost::function<void (const char*, size_t)> _callback;
-};
-
-}}} // namespace
-
-#endif //INCLUDED_ASYNC_SERIAL_HPP
diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp
index 9a695b57e..ee4ee5ca4 100644
--- a/host/lib/usrp/e300/e300_impl.cpp
+++ b/host/lib/usrp/e300/e300_impl.cpp
@@ -394,19 +394,35 @@ e300_impl::e300_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));
_eeprom_manager = boost::make_shared<e300_eeprom_manager>(i2c::make_i2cdev(E300_I2CDEV_DEVICE));
+ _sensor_manager = e300_sensor_manager::make_local(_global_regs);
}
_codec_mgr = ad936x_manager::make(_codec_ctrl, fpga::NUM_RADIOS);
- UHD_MSG(status) << "Detecting internal GPSDO.... " << std::flush;
- if (_xport_path == AXI) {
- try {
- _gps = gps::ublox::ubx::control::make("/dev/ttyPS1", 9600);
- } catch (std::exception &e) {
- UHD_MSG(error) << "An error occured making GPSDO control: " << e.what() << std::endl;
+#ifdef E300_GPSD
+ UHD_MSG(status) << "Detecting internal GPSDO " << std::flush;
+ try {
+ if (_xport_path == AXI)
+ _gps = gpsd_iface::make("localhost", 2947);
+ else
+ _gps = gpsd_iface::make(device_addr["addr"], 2947);
+ } catch (std::exception &e) {
+ UHD_MSG(error) << "An error occured making GPSDd interface: " << e.what() << std::endl;
+ }
+
+ if (_gps) {
+ for (size_t i = 0; i < _GPS_TIMEOUT; i++)
+ {
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ if (!_gps->gps_detected())
+ std::cout << "." << std::flush;
+ else {
+ std::cout << ".... " << std::flush;
+ break;
+ }
}
- _sensor_manager = e300_sensor_manager::make_local(_gps, _global_regs);
+ UHD_MSG(status) << (_gps->gps_detected() ? "found" : "not found") << std::endl;
}
- UHD_MSG(status) << (_sensor_manager->get_gps_found() ? "found" : "not found") << std::endl;
+#endif
// Verify we can talk to the e300 core control registers ...
UHD_MSG(status) << "Initializing core control..." << std::endl;
@@ -451,6 +467,15 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)
_tree->create<sensor_value_t>(mb_path / "sensors" / name)
.publish(boost::bind(&e300_sensor_manager::get_sensor, _sensor_manager, name));
}
+#ifdef E300_GPSD
+ if (_gps) {
+ BOOST_FOREACH(const std::string &name, _gps->get_sensors())
+ {
+ _tree->create<sensor_value_t>(mb_path / "sensors" / name)
+ .publish(boost::bind(&gpsd_iface::get_sensor, _gps, name));
+ }
+ }
+#endif
////////////////////////////////////////////////////////////////////
// setup the mboard eeprom
@@ -513,7 +538,11 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)
_tree->create<std::string>(mb_path / "time_source" / "value")
.subscribe(boost::bind(&e300_impl::_update_time_source, this, _1))
.set(e300::DEFAULT_TIME_SRC);
+#ifdef E300_GPSD
static const std::vector<std::string> time_sources = boost::assign::list_of("none")("internal")("external")("gpsdo");
+#else
+ static const std::vector<std::string> time_sources = boost::assign::list_of("none")("internal")("external");
+#endif
_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")
@@ -593,12 +622,25 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)
_tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(rx_spec);
_tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(tx_spec);
- UHD_MSG(status) << "Initializing time to the internal GPSDO" << std::endl;
- const time_t tp = time_t(_sensor_manager->get_sensor("gps_time").to_int()+1);
- _tree->access<time_spec_t>(mb_path / "time" / "pps").set(time_spec_t(tp));
+#ifdef E300_GPSD
+ //GPS installed: use external ref, time, and init time spec
+ if (_gps and _gps->gps_detected()) {
+ UHD_MSG(status) << "Setting references to the internal GPSDO"
+ << std::endl;
+ _tree->access<std::string>(mb_path / "time_source" / "value").set("gpsdo");
+ UHD_MSG(status) << "Initializing time to the internal GPSDO"
+ << std::endl;
+ const time_t tp = time_t(_gps->get_sensor("gps_time").to_int()+1);
+ _tree->access<time_spec_t>(mb_path / "time" / "pps").set(time_spec_t(tp));
+
+ // wait for time to be actually set
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ }
+#else
+ //init to internal clock and time source
+ _tree->access<std::string>(mb_path / "time_source/value").set("internal");
+#endif// E300_GPSD
- // wait for time to be actually set
- boost::this_thread::sleep(boost::posix_time::seconds(1));
}
boost::uint8_t e300_impl::_get_internal_gpio(gpio_core_200::sptr gpio)
@@ -792,8 +834,10 @@ void e300_impl::_update_time_source(const std::string &source)
UHD_MSG(status) << boost::format("Setting time source to %s") % source << std::endl;
if (source == "none" or source == "internal") {
_misc.pps_sel = global_regs::PPS_INT;
+#ifdef E300_GPSD
} else if (source == "gpsdo") {
_misc.pps_sel = global_regs::PPS_GPS;
+#endif
} else if (source == "external") {
_misc.pps_sel = global_regs::PPS_EXT;
} else {
diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp
index d61b95387..8aff51466 100644
--- a/host/lib/usrp/e300/e300_impl.hpp
+++ b/host/lib/usrp/e300/e300_impl.hpp
@@ -47,7 +47,11 @@
#include "e300_i2c.hpp"
#include "e300_eeprom_manager.hpp"
#include "e300_sensor_manager.hpp"
-#include "e300_ublox_control.hpp"
+
+/* if we don't compile with gpsd support, don't bother */
+#ifdef E300_GPSD
+#include "gpsd_iface.hpp"
+#endif
namespace uhd { namespace usrp { namespace e300 {
@@ -299,7 +303,10 @@ private: // members
std::string _idle_image;
bool _do_not_reload;
gpio_t _misc;
- gps::ublox::ubx::control::sptr _gps;
+#ifdef E300_GPSD
+ gpsd_iface::sptr _gps;
+ static const size_t _GPS_TIMEOUT = 5;
+#endif
};
}}} // namespace
diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp
index d68dc4541..96387d6f7 100644
--- a/host/lib/usrp/e300/e300_network.cpp
+++ b/host/lib/usrp/e300/e300_network.cpp
@@ -349,19 +349,9 @@ static void e300_sensor_tunnel(
// TODO: This is ugly ... use proper serialization
in->value = uhd::htonx<boost::uint32_t>(
e300_sensor_manager::pack_float_in_uint32_t(temp.to_real()));
- } else if (uhd::ntohx(in->which) == GPS_FOUND) {
- in->value = uhd::htonx<boost::uint32_t>(
- sensor_manager->get_gps_found() ? 1 : 0);
-
- } else if (uhd::ntohx(in->which) == GPS_LOCK) {
- in->value = uhd::htonx<boost::uint32_t>(
- sensor_manager->get_gps_lock().to_bool() ? 1 : 0);
} else if (uhd::ntohx(in->which) == REF_LOCK) {
in->value = uhd::htonx<boost::uint32_t>(
sensor_manager->get_ref_lock().to_bool() ? 1 : 0);
- } else if (uhd::ntohx(in->which) == GPS_TIME) {
- in->value = uhd::htonx<boost::uint32_t>(
- sensor_manager->get_gps_time().to_int());
} else
UHD_MSG(status) << "Got unknown request?!" << std::endl;
@@ -648,8 +638,7 @@ network_server_impl::network_server_impl(const uhd::device_addr_t &device_addr)
_codec_ctrl = ad9361_ctrl::make_spi(client_settings, spi::make(E300_SPIDEV_DEVICE), 1);
// 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), _global_regs);
+ _sensor_manager = e300_sensor_manager::make_local(_global_regs);
}
}}} // namespace
diff --git a/host/lib/usrp/e300/e300_sensor_manager.cpp b/host/lib/usrp/e300/e300_sensor_manager.cpp
index 527cfb91a..a4319fa4b 100644
--- a/host/lib/usrp/e300/e300_sensor_manager.cpp
+++ b/host/lib/usrp/e300/e300_sensor_manager.cpp
@@ -24,7 +24,6 @@
#include <cstring>
#include <uhd/exception.hpp>
#include <uhd/utils/byteswap.hpp>
-#include <uhd/usrp/gps_ctrl.hpp>
namespace uhd { namespace usrp { namespace e300 {
@@ -38,17 +37,13 @@ public:
std::vector<std::string> get_sensors()
{
- return boost::assign::list_of("temp")("gps_locked")("gps_time")("ref_locked");
+ return boost::assign::list_of("temp")("ref_locked");
}
uhd::sensor_value_t get_sensor(const std::string &key)
{
if (key == "temp")
return get_mb_temp();
- else if (key == "gps_locked")
- return get_gps_lock();
- else if (key == "gps_time")
- return get_gps_time();
else if (key == "ref_locked")
return get_ref_lock();
else
@@ -94,108 +89,6 @@ public:
"C");
}
- uhd::sensor_value_t get_gps_time(void)
- {
- boost::mutex::scoped_lock(_mutex);
- sensor_transaction_t transaction;
- transaction.which = uhd::htonx<boost::uint32_t>(GPS_TIME);
- {
- 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) == GPS_TIME);
- // TODO: Use proper serialization here ...
- return sensor_value_t("GPS epoch time", int(uhd::ntohx<boost::uint32_t>(transaction.value)), "seconds");
- }
-
- bool get_gps_found(void)
- {
- boost::mutex::scoped_lock(_mutex);
- sensor_transaction_t transaction;
- transaction.which = uhd::htonx<boost::uint32_t>(GPS_FOUND);
- {
- 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) == GPS_FOUND);
- // TODO: Use proper serialization here ...
- return (uhd::ntohx(transaction.value) > 0);
- }
-
- uhd::sensor_value_t get_gps_lock(void)
- {
- boost::mutex::scoped_lock(_mutex);
- sensor_transaction_t transaction;
- transaction.which = uhd::htonx<boost::uint32_t>(GPS_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) == GPS_LOCK);
- // TODO: Use proper serialization here ...
- return sensor_value_t("GPS lock status", (uhd::ntohx(transaction.value) > 0), "locked", "unlocked");
- }
-
uhd::sensor_value_t get_ref_lock(void)
{
boost::mutex::scoped_lock(_mutex);
@@ -255,24 +148,20 @@ 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, global_regs::sptr global_regs) :
- _gps_ctrl(gps_ctrl), _global_regs(global_regs)
+ e300_sensor_local(global_regs::sptr global_regs) :
+ _global_regs(global_regs)
{
}
std::vector<std::string> get_sensors()
{
- return boost::assign::list_of("temp")("gps_locked")("gps_time")("ref_locked");
+ return boost::assign::list_of("temp")("ref_locked");
}
uhd::sensor_value_t get_sensor(const std::string &key)
{
if (key == "temp")
return get_mb_temp();
- else if (key == "gps_locked")
- return get_gps_lock();
- else if (key == "gps_time")
- return get_gps_time();
else if (key == "ref_locked")
return get_ref_lock();
else
@@ -291,21 +180,6 @@ public:
return sensor_value_t("temp", (raw + offset) * scale / 1000, "C");
}
- bool get_gps_found(void)
- {
- return _gps_ctrl->gps_detected();
- }
-
- uhd::sensor_value_t get_gps_lock(void)
- {
- return _gps_ctrl->get_sensor("gps_locked");
- }
-
- uhd::sensor_value_t get_gps_time(void)
- {
- return _gps_ctrl->get_sensor("gps_time");
- }
-
uhd::sensor_value_t get_ref_lock(void)
{
//PPSLOOP_LOCKED_MASK is asserted in the following cases:
@@ -322,22 +196,21 @@ public:
}
private:
- 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, global_regs::sptr global_regs)
+ global_regs::sptr global_regs)
{
- return sptr(new e300_sensor_local(gps_ctrl, global_regs));
+ return sptr(new e300_sensor_local(global_regs));
}
#else
using namespace uhd::usrp::e300;
e300_sensor_manager::sptr e300_sensor_manager::make_local(
- uhd::gps_ctrl::sptr, global_regs::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 09f889251..bfaf8e90c 100644
--- a/host/lib/usrp/e300/e300_sensor_manager.hpp
+++ b/host/lib/usrp/e300/e300_sensor_manager.hpp
@@ -39,25 +39,22 @@ struct sensor_transaction_t {
-enum sensor {ZYNQ_TEMP=0, GPS_FOUND=1, GPS_TIME=2,
- GPS_LOCK=3, REF_LOCK=4};
+enum sensor {ZYNQ_TEMP=0, REF_LOCK=4};
class e300_sensor_manager : boost::noncopyable
{
public:
typedef boost::shared_ptr<e300_sensor_manager> sptr;
- virtual bool get_gps_found(void) = 0;
virtual uhd::sensor_value_t get_sensor(const std::string &key) = 0;
virtual std::vector<std::string> get_sensors(void) = 0;
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, global_regs::sptr global_regs);
+ static sptr make_local(global_regs::sptr global_regs);
// Note: This is a hack
static boost::uint32_t pack_float_in_uint32_t(const float &v)
diff --git a/host/lib/usrp/e300/e300_ublox_control.hpp b/host/lib/usrp/e300/e300_ublox_control.hpp
deleted file mode 100644
index 8705d6c52..000000000
--- a/host/lib/usrp/e300/e300_ublox_control.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef INCLUDED_UHD_USRP_UBLOX_CONTROL_HPP
-#define INCLUDED_UHD_USRP_UBLOX_CONTROL_HPP
-
-#include <boost/cstdint.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/asio.hpp>
-#include <uhd/config.hpp>
-#include <uhd/usrp/gps_ctrl.hpp>
-#include <uhd/types/sensors.hpp>
-
-#include "e300_async_serial.hpp"
-
-namespace uhd { namespace usrp { namespace gps {
-
-namespace ublox { namespace ubx {
-
-class control : public virtual uhd::gps_ctrl
-{
-public:
- typedef boost::shared_ptr<control> sptr;
-
- static sptr make(const std::string &node, const size_t baud_rate);
-
- virtual void configure_message_rate(
- const boost::uint16_t msg,
- const boost::uint8_t rate) = 0;
-
- virtual void configure_antenna(
- const boost::uint16_t flags,
- const boost::uint16_t pins) = 0;
-
- virtual void configure_pps(
- const boost::uint32_t interval,
- const boost::uint32_t length,
- const boost::int8_t status,
- const boost::uint8_t time_ref,
- const boost::uint8_t flags,
- const boost::int16_t antenna_delay,
- const boost::int16_t rf_group_delay,
- const boost::int32_t user_delay) = 0;
-
- virtual void configure_rates(
- boost::uint16_t meas_rate,
- boost::uint16_t nav_rate,
- boost::uint16_t time_ref) = 0;
-};
-}} // namespace ublox::ubx
-
-}}} // namespace
-#endif // INCLUDED_UHD_USRP_UBLOX_CONTROL_HPP
diff --git a/host/lib/usrp/e300/e300_ublox_control_impl.cpp b/host/lib/usrp/e300/e300_ublox_control_impl.cpp
deleted file mode 100644
index 389bf79fa..000000000
--- a/host/lib/usrp/e300/e300_ublox_control_impl.cpp
+++ /dev/null
@@ -1,505 +0,0 @@
-#include <boost/format.hpp>
-#include <boost/foreach.hpp>
-#include <boost/bind.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/assign/list_of.hpp>
-#include "boost/date_time/posix_time/posix_time.hpp"
-
-#include <iostream>
-
-
-#include <uhd/utils/byteswap.hpp>
-#include <uhd/utils/msg.hpp>
-#include <uhd/exception.hpp>
-
-#include "e300_ublox_control.hpp"
-
-#ifdef E300_NATIVE
-#include "e300_ublox_control_impl.hpp"
-
-
-namespace uhd { namespace usrp { namespace gps {
-
-namespace ublox { namespace ubx {
-
-control_impl::control_impl(const std::string &node, const size_t baud_rate)
-{
- _decode_init();
- _serial = boost::make_shared<async_serial>(node, baud_rate);
- _serial->set_read_callback(boost::bind(&control_impl::_rx_callback, this, _1, _2));
-
- _detect();
-
- configure_message_rate(MSG_GLL, 0);
- configure_message_rate(MSG_GSV, 0);
- configure_message_rate(MSG_GGA, 0);
- configure_message_rate(MSG_GSA, 0);
- configure_message_rate(MSG_RMC, 0);
- configure_message_rate(MSG_VTG, 0);
- configure_message_rate(MSG_NAV_TIMEUTC, 1);
- configure_message_rate(MSG_NAV_SOL, 1);
-
- configure_antenna(0x001b, 0x8251);
-
- configure_pps(0xf4240, 0x3d090, 1, 0 /* utc */, 1, 0, 0, 0);
-
- _sensors = boost::assign::list_of("gps_locked")("gps_time");
-}
-
-bool control_impl::gps_detected(void)
-{
- return _detected;
-}
-
-void control_impl::_detect(void)
-{
- _send_message(MSG_MON_VER, NULL, 0);
-}
-
-std::vector<std::string> control_impl::get_sensors(void)
-{
- return _sensors;
-}
-
-uhd::sensor_value_t control_impl::get_sensor(std::string key)
-{
- if (key == "gps_time") {
- bool lock;
- _locked.wait_and_see(lock);
- return sensor_value_t("GPS epoch time",
- lock ? int(_get_epoch_time()) : 0, "seconds");
- } else if (key == "gps_locked") {
- bool lock;
- _locked.wait_and_see(lock);
- return sensor_value_t("GPS lock status", lock, "locked", "unlocked");
- } else
- throw uhd::key_error(str(boost::format("sensor %s unknown.") % key));
-}
-
-std::time_t control_impl::_get_epoch_time(void)
-{
- boost::posix_time::ptime ptime;
- _ptime.wait_and_see(ptime);
- return (ptime - boost::posix_time::from_time_t(0)).total_seconds();
-}
-
-control_impl::~control_impl(void)
-{
-}
-
-void control_impl::_decode_init(void)
-{
- _decode_state = DECODE_SYNC1;
- _rx_ck_a = 0;
- _rx_ck_b = 0;
- _rx_payload_length = 0;
- _rx_payload_index = 0;
-}
-
-void control_impl::_add_byte_to_checksum(const boost::uint8_t b)
-{
- _rx_ck_a = _rx_ck_a + b;
- _rx_ck_b = _rx_ck_b + _rx_ck_a;
-}
-
-void control_impl::_calc_checksum(
- const boost::uint8_t *buffer,
- const boost::uint16_t length,
- checksum_t &checksum)
-{
- for (size_t i = 0; i < length; i++)
- {
- checksum.ck_a = checksum.ck_a + buffer[i];
- checksum.ck_b = checksum.ck_b + checksum.ck_a;
- }
-}
-
-void control_impl::configure_rates(
- boost::uint16_t meas_rate,
- boost::uint16_t nav_rate,
- boost::uint16_t time_ref)
-{
- payload_tx_cfg_rate_t cfg_rate;
- cfg_rate.meas_rate = uhd::htowx<boost::uint16_t>(meas_rate);
- cfg_rate.nav_rate = uhd::htowx<boost::uint16_t>(nav_rate);
- cfg_rate.time_ref = uhd::htowx<boost::uint16_t>(time_ref);
-
- _send_message(
- MSG_CFG_RATE,
- reinterpret_cast<const uint8_t*>(&cfg_rate),
- sizeof(cfg_rate));
-
- _wait_for_ack(MSG_CFG_RATE, 1.0);
-}
-
-void control_impl::configure_message_rate(
- const boost::uint16_t msg,
- const uint8_t rate)
-{
- payload_tx_cfg_msg_t cfg_msg;
- cfg_msg.msg = uhd::htowx<boost::uint16_t>(msg);
- cfg_msg.rate[0] = 0;//rate;
- cfg_msg.rate[1] = rate;
- cfg_msg.rate[2] = 0;//rate;
- cfg_msg.rate[3] = 0;//rate;
- cfg_msg.rate[4] = 0;//rate;
- cfg_msg.rate[5] = 0;//rate;
- _send_message(
- MSG_CFG_MSG,
- reinterpret_cast<const uint8_t*>(&cfg_msg),
- sizeof(cfg_msg));
-
- _wait_for_ack(MSG_CFG_MSG, 1.0);
-}
-
-void control_impl::configure_antenna(
- const boost::uint16_t flags,
- const boost::uint16_t pins)
-{
- payload_tx_cfg_ant_t cfg_ant;
- cfg_ant.pins = uhd::htowx<boost::uint16_t>(pins);
- cfg_ant.flags = uhd::htowx<boost::uint16_t>(flags);
- _send_message(
- MSG_CFG_ANT,
- reinterpret_cast<const uint8_t*>(&cfg_ant),
- sizeof(cfg_ant));
- if (_wait_for_ack(MSG_CFG_ANT, 1.0) < 0) {
- throw uhd::runtime_error("Didn't get an ACK for antenna configuration.");
- }
-
-}
-
-void control_impl::configure_pps(
- const boost::uint32_t interval,
- const boost::uint32_t length,
- const boost::int8_t status,
- const boost::uint8_t time_ref,
- const boost::uint8_t flags,
- const boost::int16_t antenna_delay,
- const boost::int16_t rf_group_delay,
- const boost::int32_t user_delay)
-{
- payload_tx_cfg_tp_t cfg_tp;
- cfg_tp.interval = uhd::htowx<boost::uint32_t>(interval);
- cfg_tp.length = uhd::htowx<boost::uint32_t>(length);
- cfg_tp.status = status;
- cfg_tp.time_ref = time_ref;
- cfg_tp.flags = flags;
- cfg_tp.antenna_delay = uhd::htowx<boost::int16_t>(antenna_delay);
- cfg_tp.rf_group_delay = uhd::htowx<boost::int16_t>(rf_group_delay);
- cfg_tp.user_delay = uhd::htowx<boost::int32_t>(user_delay);
- _send_message(
- MSG_CFG_TP,
- reinterpret_cast<const uint8_t*>(&cfg_tp),
- sizeof(cfg_tp));
- if (_wait_for_ack(MSG_CFG_TP, 1.0) < 0) {
- throw uhd::runtime_error("Didn't get an ACK for PPS configuration.");
- }
-}
-
-
-void control_impl::_rx_callback(const char *data, unsigned int len)
-{
- //std::cout << "IN RX CALLBACK" << std::flush << std::endl;
- std::vector<char> v(data, data+len);
- BOOST_FOREACH(const char &c, v)
- {
- _parse_char(c);
- }
-}
-
-void control_impl::_parse_char(const boost::uint8_t b)
-{
- int ret = 0;
-
- switch (_decode_state) {
-
- // we're expecting the first sync byte
- case DECODE_SYNC1:
- if (b == SYNC1) { // sync1 found goto next step
- _decode_state = DECODE_SYNC2;
- } // else stay around
- break;
-
- // we're expecting the second sync byte
- case DECODE_SYNC2:
- if (b == SYNC2) { // sync2 found goto next step
- _decode_state = DECODE_CLASS;
- } else {
- // failed, reset
- _decode_init();
- }
- break;
-
- // we're expecting the class byte
- case DECODE_CLASS:
- _add_byte_to_checksum(b);
- _rx_msg = b;
- _decode_state = DECODE_ID;
- break;
-
- // we're expecting the id byte
- case DECODE_ID:
- _add_byte_to_checksum(b);
- _rx_msg |= (b << 8);
- _decode_state = DECODE_LENGTH1;
- break;
-
- // we're expecting the first length byte
- case DECODE_LENGTH1:
- _add_byte_to_checksum(b);
- _rx_payload_length = b;
- _decode_state = DECODE_LENGTH2;
- break;
-
- // we're expecting the second length byte
- case DECODE_LENGTH2:
- _add_byte_to_checksum(b);
- _rx_payload_length |= (b << 8);
- if(_payload_rx_init()) {
- _decode_init(); // we failed, give up for this one
- } else {
- _decode_state = _rx_payload_length ?
- DECODE_PAYLOAD : DECODE_CHKSUM1;
- }
- break;
-
- // we're expecting payload
- case DECODE_PAYLOAD:
- _add_byte_to_checksum(b);
- switch(_rx_msg) {
- default:
- ret = _payload_rx_add(b);
- break;
- };
- if (ret < 0) {
- // we couldn't deal with the payload, discard the whole thing
- _decode_init();
- } else if (ret > 0) {
- // payload was complete, let's check the checksum;
- _decode_state = DECODE_CHKSUM1;
- } else {
- // more payload expected, don't move
- }
- ret = 0;
- break;
-
- case DECODE_CHKSUM1:
- if (_rx_ck_a != b) {
- // checksum didn't match, barf
- std::cout << boost::format("Failed checksum byte1 %lx != %lx")
- % int(_rx_ck_a) % int(b) << std::endl;
- _decode_init();
- } else {
- _decode_state = DECODE_CHKSUM2;
- }
- break;
-
- case DECODE_CHKSUM2:
- if (_rx_ck_b != b) {
- // checksum didn't match, barf
- std::cout << boost::format("Failed checksum byte2 %lx != %lx")
- % int(_rx_ck_b) % int(b) << std::endl;
-
- } else {
- ret = _payload_rx_done(); // payload done
- }
- _decode_init();
- break;
-
- default:
- break;
- };
-}
-
-int control_impl::_payload_rx_init(void)
-{
- int ret = 0;
-
- _rx_state = RXMSG_HANDLE; // by default handle
- switch(_rx_msg) {
-
- case MSG_NAV_SOL:
- if (not (_rx_payload_length == sizeof(payload_rx_nav_sol_t)))
- _rx_state = RXMSG_ERROR_LENGTH;
- break;
-
- case MSG_NAV_TIMEUTC:
- if (not (_rx_payload_length == sizeof(payload_rx_nav_timeutc_t)))
- _rx_state = RXMSG_ERROR_LENGTH;
- break;
-
- case MSG_MON_VER:
- break; // always take this one
-
- case MSG_ACK_ACK:
- if (not (_rx_payload_length == sizeof(payload_rx_ack_ack_t)))
- _rx_state = RXMSG_ERROR_LENGTH;
- break;
-
- case MSG_ACK_NAK:
- if (not (_rx_payload_length == sizeof(payload_rx_ack_nak_t)))
- _rx_state = RXMSG_ERROR_LENGTH;
- break;
-
- default:
- _rx_state = RXMSG_DISABLE;
- break;
- };
-
- switch (_rx_state) {
- case RXMSG_HANDLE: // handle message
- case RXMSG_IGNORE: // ignore message but don't report error
- ret = 0;
- break;
- case RXMSG_DISABLE: // ignore message but don't report error
- case RXMSG_ERROR_LENGTH: // the length doesn't match
- ret = -1;
- break;
- default: // invalid, error
- ret = -1;
- break;
- };
-
- return ret;
-}
-
-int control_impl::_payload_rx_add(const boost::uint8_t b)
-{
- int ret = 0;
- _buf.raw[_rx_payload_index] = b;
- if (++_rx_payload_index >= _rx_payload_length)
- ret = 1;
- return ret;
-}
-
-int control_impl::_payload_rx_done(void)
-{
- int ret = 0;
- if (_rx_state != RXMSG_HANDLE) {
- return 0;
- }
-
- switch (_rx_msg) {
- case MSG_MON_VER:
- _detected = true;
- break;
-
- case MSG_MON_HW:
- std::cout << "MON-HW" << std::endl;
- break;
-
- case MSG_ACK_ACK:
- if ((_ack_state == ACK_WAITING) and (_buf.payload_rx_ack_ack.msg == _ack_waiting_msg))
- _ack_state = ACK_GOT_ACK;
- break;
-
- case MSG_ACK_NAK:
- if ((_ack_state == ACK_WAITING) and (_buf.payload_rx_ack_nak.msg == _ack_waiting_msg))
- _ack_state = ACK_GOT_NAK;
-
- break;
-
- case MSG_CFG_ANT:
- break;
-
- case MSG_NAV_TIMEUTC:
- _ptime.update(boost::posix_time::ptime(
- boost::gregorian::date(
- boost::gregorian::greg_year(uhd::wtohx<boost::uint16_t>(
- _buf.payload_rx_nav_timeutc.year)),
- boost::gregorian::greg_month(_buf.payload_rx_nav_timeutc.month),
- boost::gregorian::greg_day(_buf.payload_rx_nav_timeutc.day)),
- (boost::posix_time::hours(_buf.payload_rx_nav_timeutc.hour)
- + boost::posix_time::minutes(_buf.payload_rx_nav_timeutc.min)
- + boost::posix_time::seconds(_buf.payload_rx_nav_timeutc.sec))));
- break;
-
- case MSG_NAV_SOL:
- _locked.update(_buf.payload_rx_nav_sol.gps_fix > 0);
- break;
-
- default:
- std::cout << boost::format("Got unknown message %lx , with good checksum [") % int(_rx_msg);
- for(size_t i = 0; i < _rx_payload_length; i++)
- std::cout << boost::format("%lx, ") % int(_buf.raw[i]);
- std::cout << "]"<< std::endl;
- break;
- };
- return ret;
-}
-
-void control_impl::_send_message(
- const boost::uint16_t msg,
- const boost::uint8_t *payload,
- const boost::uint16_t len)
-{
- header_t header = {SYNC1, SYNC2, msg, len};
- checksum_t checksum = {0, 0};
-
- // calculate checksums, first header without sync
- // then payload
- _calc_checksum(
- reinterpret_cast<boost::uint8_t*>(&header) + 2,
- sizeof(header) - 2, checksum);
- if (payload)
- _calc_checksum(payload, len, checksum);
-
- _serial->write(
- reinterpret_cast<const char*>(&header),
- sizeof(header));
-
- if (payload)
- _serial->write((const char *) payload, len);
-
- _serial->write(
- reinterpret_cast<const char*>(&checksum),
- sizeof(checksum));
-}
-
-int control_impl::_wait_for_ack(
- const boost::uint16_t msg,
- const double timeout)
-{
- int ret = -1;
-
- _ack_state = ACK_WAITING;
- _ack_waiting_msg = msg;
-
- boost::system_time timeout_time =
- boost::get_system_time() +
- boost::posix_time::milliseconds(timeout * 1000.0);
-
- do {
- if(_ack_state == ACK_GOT_ACK)
- return 0;
- else if (_ack_state == ACK_GOT_NAK) {
- return -1;
- }
- boost::this_thread::sleep(boost::posix_time::milliseconds(20));
- } while (boost::get_system_time() < timeout_time);
-
- // we get here ... it's a timeout
- _ack_state = ACK_IDLE;
- return ret;
-}
-
-
-}} // namespace ublox::ubx
-}}} // namespace
-
-using namespace uhd::usrp::gps::ublox::ubx;
-
-control::sptr control::make(const std::string &node, const size_t baud_rate)
-{
- return control::sptr(new control_impl(node, baud_rate));
-}
-#else
-using namespace uhd::usrp::gps::ublox::ubx;
-
-control::sptr control::make(const std::string& /* node */, const size_t /* baud_rate */)
-{
- throw uhd::assertion_error("control::sptr::make: !E300_NATIVE");
-}
-#endif // E300_NATIVE
diff --git a/host/lib/usrp/e300/e300_ublox_control_impl.hpp b/host/lib/usrp/e300/e300_ublox_control_impl.hpp
deleted file mode 100644
index a1dcbfe6c..000000000
--- a/host/lib/usrp/e300/e300_ublox_control_impl.hpp
+++ /dev/null
@@ -1,457 +0,0 @@
-#ifndef INCLUDED_UHD_USRP_UBLOX_CONTROL_IMPL_HPP
-#define INCLUDED_UHD_USRP_UBLOX_CONTROL_IMPL_HPP
-
-#include <boost/cstdint.hpp>
-#include <boost/noncopyable.hpp>
-#include <boost/asio.hpp>
-#include <uhd/config.hpp>
-#include <uhd/usrp/gps_ctrl.hpp>
-#include <uhd/types/sensors.hpp>
-
-#include "e300_async_serial.hpp"
-
-namespace uhd { namespace usrp { namespace gps {
-
-namespace ublox { namespace ubx {
-// ublox binary sync words
-static const boost::uint8_t SYNC1 = 0xB5;
-static const boost::uint8_t SYNC2 = 0x62;
-
-// message classes
-static const boost::uint8_t CLASS_NAV = 0x01;
-static const boost::uint8_t CLASS_ACK = 0x05;
-static const boost::uint8_t CLASS_CFG = 0x06;
-static const boost::uint8_t CLASS_MON = 0x0a;
-static const boost::uint8_t CLASS_NMEA = 0xf0;
-
-// Message IDs
-static const boost::uint8_t ID_NAV_POSLLH = 0x02;
-static const boost::uint8_t ID_NAV_SOL = 0x06;
-static const boost::uint8_t ID_NAV_PVT = 0x07;
-static const boost::uint8_t ID_NAV_VELNED = 0x12;
-static const boost::uint8_t ID_NAV_TIMEUTC = 0x21;
-static const boost::uint8_t ID_NAV_SVINFO = 0x30;
-static const boost::uint8_t ID_ACK_NAK = 0x00;
-static const boost::uint8_t ID_ACK_ACK = 0x01;
-static const boost::uint8_t ID_CFG_PRT = 0x00;
-static const boost::uint8_t ID_CFG_ANT = 0x13;
-static const boost::uint8_t ID_CFG_TP = 0x07;
-static const boost::uint8_t ID_CFG_MSG = 0x01;
-static const boost::uint8_t ID_CFG_RATE = 0x08;
-static const boost::uint8_t ID_CFG_NAV5 = 0x24;
-static const boost::uint8_t ID_MON_VER = 0x04;
-static const boost::uint8_t ID_MON_HW = 0x09;
-static const boost::uint8_t ID_GGA = 0x00;
-static const boost::uint8_t ID_GLL = 0x01;
-static const boost::uint8_t ID_GSA = 0x02;
-static const boost::uint8_t ID_GSV = 0x03;
-static const boost::uint8_t ID_RMC = 0x04;
-static const boost::uint8_t ID_VTG = 0x05;
-static const boost::uint8_t ID_GST = 0x07;
-
-// Message Classes & IDs //
-static const boost::uint16_t MSG_NAV_POSLLH
- = CLASS_NAV | (ID_NAV_POSLLH << 8);
-static const boost::uint16_t MSG_NAV_SOL
- = CLASS_NAV | (ID_NAV_SOL << 8);
-static const boost::uint16_t MSG_NAV_PVT
- = CLASS_NAV | (ID_NAV_PVT << 8);
-static const boost::uint16_t MSG_NAV_VELNED
- = CLASS_NAV | (ID_NAV_VELNED << 8);
-static const boost::uint16_t MSG_NAV_TIMEUTC
- = CLASS_NAV | (ID_NAV_TIMEUTC << 8);
-static const boost::uint16_t MSG_NAV_SVINFO
- = CLASS_NAV | (ID_NAV_SVINFO << 8);
-static const boost::uint16_t MSG_ACK_NAK
- = CLASS_ACK | (ID_ACK_NAK << 8);
-static const boost::uint16_t MSG_ACK_ACK
- = CLASS_ACK | (ID_ACK_ACK << 8);
-static const boost::uint16_t MSG_CFG_PRT
- = CLASS_CFG | (ID_CFG_PRT << 8);
-static const boost::uint16_t MSG_CFG_ANT
- = CLASS_CFG | (ID_CFG_ANT << 8);
-static const boost::uint16_t MSG_CFG_TP
- = CLASS_CFG | (ID_CFG_TP << 8);
-static const boost::uint16_t MSG_CFG_MSG
- = CLASS_CFG | (ID_CFG_MSG << 8);
-static const boost::uint16_t MSG_CFG_RATE
- = CLASS_CFG | (ID_CFG_RATE << 8);
-static const boost::uint16_t MSG_CFG_NAV5
- = CLASS_CFG | (ID_CFG_NAV5 << 8);
-static const boost::uint16_t MSG_MON_HW
- = CLASS_MON | (ID_MON_HW << 8);
-static const boost::uint16_t MSG_MON_VER
- = CLASS_MON | (ID_MON_VER << 8);
-
-// NMEA ones
-static const boost::uint16_t MSG_GGA
- = CLASS_NMEA | (ID_GGA << 8);
-static const boost::uint16_t MSG_GLL
- = CLASS_NMEA | (ID_GLL << 8);
-static const boost::uint16_t MSG_GSA
- = CLASS_NMEA | (ID_GSA << 8);
-static const boost::uint16_t MSG_GSV
- = CLASS_NMEA | (ID_GSV << 8);
-static const boost::uint16_t MSG_RMC
- = CLASS_NMEA | (ID_RMC << 8);
-static const boost::uint16_t MSG_VTG
- = CLASS_NMEA | (ID_VTG << 8);
-
-// header
-struct header_t
-{
- boost::uint8_t sync1;
- boost::uint8_t sync2;
- boost::uint16_t msg;
- boost::uint16_t length;
-};
-
-// checksum
-struct checksum_t
-{
- boost::uint8_t ck_a;
- boost::uint8_t ck_b;
-};
-
-// rx rx mon-hw (ubx6)
-struct payload_rx_mon_hw_t
-{
- boost::uint32_t pin_sel;
- boost::uint32_t pin_bank;
- boost::uint32_t pin_dir;
- boost::uint32_t pin_val;
- boost::uint16_t noise_per_ms;
- boost::uint16_t agc_cnt;
- boost::uint8_t a_status;
- boost::uint8_t a_power;
- boost::uint8_t flags;
- boost::uint8_t reserved1;
- boost::uint32_t used_mask;
- boost::uint8_t vp[25];
- boost::uint8_t jam_ind;
- boost::uint16_t reserved3;
- boost::uint32_t pin_irq;
- boost::uint32_t pullh;
- boost::uint32_t pulll;
-};
-
-// rx mon-ver
-struct payload_rx_mon_ver_part1_t
-{
- char sw_version[30];
- char hw_version[10];
-};
-
-struct payload_rx_mon_ver_part2_t
-{
- boost::uint8_t extension[30];
-};
-
-// rx ack-ack
-typedef union {
- boost::uint16_t msg;
- struct {
- boost::uint8_t cls_id;
- boost::uint8_t msg_id;
- };
-} payload_rx_ack_ack_t;
-
-// rx ack-nak
-typedef union {
- boost::uint16_t msg;
- struct {
- boost::uint8_t cls_id;
- boost::uint8_t msg_id;
- };
-} payload_rx_ack_nak_t;
-
-// tx cfg-prt (uart)
-struct payload_tx_cfg_prt_t
-{
- boost::uint8_t port_id;
- boost::uint8_t reserved0;
- boost::uint16_t tx_ready;
- boost::uint32_t mode;
- boost::uint32_t baud_rate;
- boost::uint16_t in_proto_mask;
- boost::uint16_t out_proto_mask;
- boost::uint16_t flags;
- boost::uint16_t reserved5;
-};
-
-// tx cfg-rate
-struct payload_tx_cfg_rate_t
-{
- boost::uint16_t meas_rate;
- boost::uint16_t nav_rate;
- boost::uint16_t time_ref;
-};
-
-// tx cfg-msg
-struct payload_tx_cfg_msg_t
-{
- boost::uint16_t msg;
- boost::uint8_t rate[6];
-};
-
-
-// tx cfg-ant
-struct payload_tx_cfg_ant_t
-{
- boost::uint16_t flags;
- boost::uint16_t pins;
-};
-
-// tx cfg-tp
-struct payload_tx_cfg_tp_t
-{
- boost::uint32_t interval;
- boost::uint32_t length;
- boost::int8_t status;
- boost::uint8_t time_ref;
- boost::uint8_t flags;
- boost::uint8_t reserved1;
- boost::int16_t antenna_delay;
- boost::int16_t rf_group_delay;
- boost::int32_t user_delay;
-};
-
-struct payload_rx_nav_sol_t
-{
- boost::uint32_t i_tow;
- boost::int32_t f_tow;
- boost::int16_t week;
- boost::uint8_t gps_fix;
- boost::uint8_t flags;
- boost::int32_t ecef_x;
- boost::int32_t ecef_y;
- boost::int32_t ecef_z;
- boost::uint32_t p_acc;
- boost::int32_t ecef_vx;
- boost::int32_t ecef_vy;
- boost::int32_t ecef_vz;
- boost::uint32_t s_acc;
- boost::uint16_t p_dop;
- boost::uint8_t reserved1;
- boost::uint8_t num_sv;
- boost::uint32_t reserved2;
-};
-
-struct payload_rx_nav_timeutc_t
-{
- boost::uint32_t i_tow;
- boost::uint32_t t_acc;
- boost::int32_t nano;
- boost::uint16_t year;
- boost::uint8_t month;
- boost::uint8_t day;
- boost::uint8_t hour;
- boost::uint8_t min;
- boost::uint8_t sec;
- boost::uint8_t valid;
-};
-
-typedef union {
- payload_rx_mon_hw_t payload_rx_mon_hw;
-
- payload_rx_mon_ver_part1_t payload_rx_mon_ver_part1;
- payload_rx_mon_ver_part2_t payload_rx_mon_ver_part2;
-
- payload_rx_ack_ack_t payload_rx_ack_ack;
- payload_rx_ack_nak_t payload_rx_ack_nak;
-
- payload_tx_cfg_prt_t payload_tx_cfg_prt;
- payload_tx_cfg_ant_t payload_tx_cfg_ant;
- payload_tx_cfg_rate_t payload_tx_cfg_rate;
-
- payload_tx_cfg_msg_t payload_tx_cfg_msg;
-
- payload_rx_nav_timeutc_t payload_rx_nav_timeutc;
- payload_rx_nav_sol_t payload_rx_nav_sol;
- boost::uint8_t raw[];
-} buf_t;
-
-
-template <typename T>
-class sensor_entry
-{
-public:
- sensor_entry() : _seen(false)
- {
- }
-
- void update(const T &val)
- {
- boost::mutex::scoped_lock l(_mutex);
- _value = val;
- _seen = false;
- l.unlock();
- _cond.notify_one();
- }
-
- bool seen() const
- {
- boost::mutex::scoped_lock l(_mutex);
- return _seen;
- }
-
- bool try_and_see(T &val)
- {
- boost::mutex::scoped_lock l(_mutex);
- if (_seen)
- return false;
-
- val = _value;
- _seen = true;
- return true;
- }
-
- void wait_and_see(T &val)
- {
- boost::mutex::scoped_lock l(_mutex);
- while(_seen)
- {
- _cond.wait(l);
- //std::cout << "Already seen ... " << std::endl;
- }
- val = _value;
- _seen = true;
- }
-
-private: // members
- T _value;
- boost::mutex _mutex;
- boost::condition_variable _cond;
- bool _seen;
-};
-
-class control_impl : public control
-{
-public:
- control_impl(const std::string &node, const size_t baud_rate);
-
- virtual ~control_impl(void);
-
- void configure_message_rate(
- const boost::uint16_t msg,
- const boost::uint8_t rate);
-
- void configure_antenna(
- const boost::uint16_t flags,
- const boost::uint16_t pins);
-
- void configure_pps(
- const boost::uint32_t interval,
- const boost::uint32_t length,
- const boost::int8_t status,
- const boost::uint8_t time_ref,
- const boost::uint8_t flags,
- const boost::int16_t antenna_delay,
- const boost::int16_t rf_group_delay,
- const boost::int32_t user_delay);
-
- void configure_rates(
- boost::uint16_t meas_rate,
- boost::uint16_t nav_rate,
- boost::uint16_t time_ref);
-
- // gps_ctrl interface
- bool gps_detected(void);
- std::vector<std::string> get_sensors(void);
- uhd::sensor_value_t get_sensor(std::string key);
-
-private: // types
- enum decoder_state_t {
- DECODE_SYNC1 = 0,
- DECODE_SYNC2,
- DECODE_CLASS,
- DECODE_ID,
- DECODE_LENGTH1,
- DECODE_LENGTH2,
- DECODE_PAYLOAD,
- DECODE_CHKSUM1,
- DECODE_CHKSUM2,
- };
-
- enum rxmsg_state_t {
- RXMSG_IGNORE = 0,
- RXMSG_HANDLE,
- RXMSG_DISABLE,
- RXMSG_ERROR_LENGTH
- };
-
- enum ack_state_t {
- ACK_IDLE = 0,
- ACK_WAITING,
- ACK_GOT_ACK,
- ACK_GOT_NAK
- };
-
-private: // methods
- std::time_t _get_epoch_time(void);
-
- void _decode_init(void);
-
- void _add_byte_to_checksum(const boost::uint8_t b);
-
- void _detect(void);
-
- void _send_message(
- const boost::uint16_t msg,
- const boost::uint8_t *payload,
- const boost::uint16_t len);
-
- int _wait_for_ack(
- const boost::uint16_t msg,
- const double timeout);
-
- void _calc_checksum(
- const boost::uint8_t *buffer,
- const boost::uint16_t length,
- checksum_t &checksum);
-
- void _rx_callback(const char *data, unsigned len);
-
- void _parse_char(const boost::uint8_t b);
-
- int _payload_rx_init(void);
-
- int _payload_rx_add(const boost::uint8_t b);
-
- int _payload_rx_done(void);
-
-private: // members
- // gps_ctrl stuff
- bool _detected;
- std::vector<std::string> _sensors;
-
- sensor_entry<bool> _locked;
- sensor_entry<boost::posix_time::ptime> _ptime;
-
- // decoder state
- decoder_state_t _decode_state;
- rxmsg_state_t _rxmsg_state;
-
- ack_state_t _ack_state;
- boost::uint16_t _ack_waiting_msg;
-
- boost::uint8_t _rx_ck_a;
- boost::uint8_t _rx_ck_b;
-
- boost::uint16_t _rx_payload_length;
- size_t _rx_payload_index;
- boost::uint16_t _rx_msg;
-
- rxmsg_state_t _rx_state;
-
- boost::shared_ptr<async_serial> _serial;
-
- // this has to be at the end of the
- // class to be valid C++
- buf_t _buf;
-};
-
-}} // namespace ublox::ubx
-
-}}} // namespace
-#endif // INCLUDED_UHD_USRP_UBLOX_CONTROL_IMPL_HPP
diff --git a/host/lib/usrp/gpsd_iface.cpp b/host/lib/usrp/gpsd_iface.cpp
new file mode 100644
index 000000000..62b6939c5
--- /dev/null
+++ b/host/lib/usrp/gpsd_iface.cpp
@@ -0,0 +1,184 @@
+//
+// Copyright 2015 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 <cmath>
+
+#include <gps.h>
+
+#include <boost/assign/list_of.hpp>
+#include <boost/bind.hpp>
+#include <boost/cstdint.hpp>
+#include "boost/date_time/gregorian/gregorian.hpp"
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread.hpp>
+
+#include <uhd/exception.hpp>
+#include <uhd/usrp/gps_ctrl.hpp>
+#include <uhd/utils/msg.hpp>
+#include <uhd/types/dict.hpp>
+
+#include "gpsd_iface.hpp"
+
+namespace uhd { namespace usrp {
+
+static const size_t TIMEOUT = 240;
+static const size_t CLICK_RATE = 250000;
+
+class gpsd_iface_impl : public virtual gpsd_iface {
+public:
+ gpsd_iface_impl(const std::string &addr, boost::uint16_t port)
+ : _detected(false), _bthread(), _timeout_cnt(0)
+ {
+ boost::unique_lock<boost::shared_mutex> l(_d_mutex);
+
+ if (gps_open(addr.c_str(),
+ str(boost::format("%u") % port).c_str(),
+ &_gps_data) < 0) {
+ throw uhd::runtime_error(
+ str((boost::format("Failed to connect to gpsd: %s")
+ % gps_errstr(errno))));
+ }
+
+ // register for updates, we don't specify a specific device,
+ // therefore no WATCH_DEVICE
+ gps_stream(&_gps_data, WATCH_ENABLE, NULL);
+
+ // create background thread talking to gpsd
+ boost::thread t(boost::bind(&gpsd_iface_impl::_thread_fcn ,this));
+ _bthread.swap(t);
+
+
+ _sensors = boost::assign::list_of("gps_locked")("gps_time")("gps_position");
+ }
+
+ virtual ~gpsd_iface_impl(void)
+ {
+ // interrupt the background thread and wait for it to finish
+ _bthread.interrupt();
+ _bthread.join();
+
+ // clean up ...
+ {
+ boost::unique_lock<boost::shared_mutex> l(_d_mutex);
+
+ gps_stream(&_gps_data, WATCH_DISABLE, NULL);
+ gps_close(&_gps_data);
+ }
+ }
+
+ uhd::sensor_value_t get_sensor(std::string key)
+ {
+ if (key == "gps_locked") {
+ return sensor_value_t(
+ "GPS lock status", _gps_locked(), "locked", "unlocked");
+ } else if (key == "gps_time") {
+ return sensor_value_t(
+ "GPS epoch time", int(_epoch_time()), "seconds");
+ } else if (key == "gps_position") {
+ return sensor_value_t(
+ "GPS Position", str(
+ boost::format("%s %s %s")
+ % _gps_position()["lat"]
+ % _gps_position()["lon"]
+ % _gps_position()["alt"]), "lat/lon/alt");
+ } else
+ throw uhd::key_error(
+ str(boost::format("sensor %s unknown.") % key));
+ }
+
+ bool gps_detected(void) { return _detected; };
+
+ std::vector<std::string> get_sensors(void) { return _sensors; };
+
+private: // member functions
+ void _thread_fcn()
+ {
+ while (not boost::this_thread::interruption_requested()) {
+ if (!gps_waiting(&_gps_data, CLICK_RATE)) {
+ if (TIMEOUT < _timeout_cnt++)
+ _detected = false;
+ } else {
+ boost::unique_lock<boost::shared_mutex> l(_d_mutex);
+
+ _timeout_cnt = 0;
+ _detected = true;
+
+ if (gps_read(&_gps_data) < 0)
+ throw std::runtime_error("error while reading");
+ }
+ }
+ }
+
+ bool _gps_locked(void)
+ {
+ boost::shared_lock<boost::shared_mutex> l(_d_mutex);
+ return _gps_data.fix.mode >= MODE_2D;
+ }
+
+ std::time_t _epoch_time(void)
+ {
+ boost::shared_lock<boost::shared_mutex> l(_d_mutex);
+ return (boost::posix_time::from_time_t(_gps_data.fix.time)
+ - boost::posix_time::from_time_t(0)).total_seconds();
+ }
+
+ boost::gregorian::date _gregorian_date(void)
+ {
+ boost::shared_lock<boost::shared_mutex> l(_d_mutex);
+ return boost::posix_time::from_time_t(_gps_data.fix.time).date();
+ }
+
+ uhd::dict<std::string, std::string> _gps_position(void)
+ {
+ boost::shared_lock<boost::shared_mutex> l(_d_mutex);
+
+ uhd::dict<std::string, std::string> tmp;
+ if (_gps_data.fix.mode >= MODE_2D) {
+ tmp["lon"] = str(boost::format("%f deg")
+ % _gps_data.fix.longitude);
+ tmp["lat"] = str(boost::format("%f deg")
+ % _gps_data.fix.latitude);
+ tmp["alt"] = str(boost::format("%fm")
+ % _gps_data.fix.altitude);
+ } else {
+ tmp["lon"] = "n/a";
+ tmp["lat"] = "n/a";
+ tmp["alt"] = "n/a";
+ }
+ return tmp;
+ }
+
+private: // members
+ std::vector<std::string> _sensors;
+ bool _detected;
+
+ gps_data_t _gps_data;
+ boost::shared_mutex _d_mutex;
+ boost::thread _bthread;
+ size_t _timeout_cnt;
+};
+
+}} //namespace
+
+using namespace uhd::usrp;
+
+gpsd_iface::sptr gpsd_iface::make(const std::string &addr, const boost::uint16_t port)
+{
+ return gpsd_iface::sptr(new gpsd_iface_impl(addr, port));
+}
diff --git a/host/lib/usrp/gpsd_iface.hpp b/host/lib/usrp/gpsd_iface.hpp
new file mode 100644
index 000000000..7d934ae5c
--- /dev/null
+++ b/host/lib/usrp/gpsd_iface.hpp
@@ -0,0 +1,36 @@
+//
+// Copyright 2015 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/>.
+//
+
+#ifndef INCLUDED_GPSD_IFACE_HPP
+#define INCLUDED_GPSD_IFACE_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <uhd/usrp/gps_ctrl.hpp>
+
+namespace uhd { namespace usrp {
+
+class gpsd_iface : public virtual uhd::gps_ctrl {
+public:
+ typedef boost::shared_ptr<gpsd_iface> sptr;
+ static sptr make(const std::string &addr, boost::uint16_t port);
+};
+
+}};
+
+#endif /* INCLUDED_GPSD_IFACE_HPP */