aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/e300/e300_ublox_control_impl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/e300/e300_ublox_control_impl.hpp')
-rw-r--r--host/lib/usrp/e300/e300_ublox_control_impl.hpp457
1 files changed, 457 insertions, 0 deletions
diff --git a/host/lib/usrp/e300/e300_ublox_control_impl.hpp b/host/lib/usrp/e300/e300_ublox_control_impl.hpp
new file mode 100644
index 000000000..a1dcbfe6c
--- /dev/null
+++ b/host/lib/usrp/e300/e300_ublox_control_impl.hpp
@@ -0,0 +1,457 @@
+#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