btnrf52-gps/lib/NeoGPS/examples/ublox/ublox.ino

400 lines
12 KiB
C++

#include <NeoGPS_cfg.h>
#include <ublox/ubxGPS.h>
//======================================================================
// Program: ublox.ino
//
// Prerequisites:
// 1) You have a ublox GPS device
// 2) PUBX.ino works with your device
// 3) You have installed the ubxGPS.* and ubxmsg.* files.
// 4) At least one UBX message has been enabled in ubxGPS.h.
// 5) Implicit Merging is disabled in NMEAGPS_cfg.h.
//
// Description: This program parses UBX binary protocal messages from
// ublox devices. It shows how to acquire the information necessary
// to use the GPS Time-Of-Week in many UBX messages. As an offset
// from midnight Sunday morning (GPS time), you also need the current
// UTC time (this is *not* GPS time) and the current number of GPS
// leap seconds.
//
// Serial is for debug output to the Serial Monitor window.
//
// License:
// Copyright (C) 2014-2017, SlashDevin
//
// This file is part of NeoGPS
//
// NeoGPS 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.
//
// NeoGPS 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 NeoGPS. If not, see <http://www.gnu.org/licenses/>.
//
//======================================================================
#include <GPSport.h>
#include <Streamers.h>
//------------------------------------------------------------
// Check that the config files are set up properly
#ifndef NMEAGPS_DERIVED_TYPES
#error You must "#define NMEAGPS_DERIVED_TYPES" in NMEAGPS_cfg.h!
#endif
#if !defined(UBLOX_PARSE_STATUS) & !defined(UBLOX_PARSE_TIMEGPS) & \
!defined(UBLOX_PARSE_TIMEUTC) & !defined(UBLOX_PARSE_POSLLH) & \
!defined(UBLOX_PARSE_DOP) & !defined(UBLOX_PARSE_PVT) & \
!defined(UBLOX_PARSE_VELNED) & !defined(UBLOX_PARSE_SVINFO) & \
!defined(UBLOX_PARSE_HNR_PVT)
#error No UBX binary messages enabled: no fix data available.
#endif
#ifndef NMEAGPS_RECOGNIZE_ALL
// Resetting the messages with ublox::configNMEA requires that
// all message types are recognized (i.e., the enum has all
// values).
#error You must "#define NMEAGPS_RECOGNIZE_ALL" in NMEAGPS_cfg.h!
#endif
//-----------------------------------------------------------------
// Derive a class to add the state machine for starting up:
// 1) The status must change to something other than NONE.
// 2) The GPS leap seconds must be received
// 3) The UTC time must be received
// 4) All configured messages are "requested"
// (i.e., "enabled" in the ublox device)
// Then, all configured messages are parsed and explicitly merged.
class MyGPS : public ubloxGPS
{
public:
enum
{
GETTING_STATUS,
GETTING_LEAP_SECONDS,
GETTING_UTC,
RUNNING
}
state NEOGPS_BF(8);
MyGPS( Stream *device ) : ubloxGPS( device )
{
state = GETTING_STATUS;
}
//--------------------------
void get_status()
{
static bool acquiring = false;
if (fix().status == gps_fix::STATUS_NONE) {
static uint32_t dotPrint;
bool requestNavStatus = false;
if (!acquiring) {
acquiring = true;
dotPrint = millis();
DEBUG_PORT.print( F("Acquiring...") );
requestNavStatus = true;
} else if (millis() - dotPrint > 1000UL) {
dotPrint = millis();
DEBUG_PORT << '.';
static uint8_t requestPeriod;
if ((++requestPeriod & 0x07) == 0)
requestNavStatus = true;
}
if (requestNavStatus)
// Turn on the UBX status message
enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_STATUS );
} else {
if (acquiring)
DEBUG_PORT << '\n';
DEBUG_PORT << F("Acquired status: ") << (uint8_t) fix().status << '\n';
#if defined(GPS_FIX_TIME) & defined(GPS_FIX_DATE) & \
defined(UBLOX_PARSE_TIMEGPS)
if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEGPS ))
DEBUG_PORT.println( F("enable TIMEGPS failed!") );
state = GETTING_LEAP_SECONDS;
#else
start_running();
state = RUNNING;
#endif
}
} // get_status
//--------------------------
void get_leap_seconds()
{
#if defined(GPS_FIX_TIME) & defined(GPS_FIX_DATE) & \
defined(UBLOX_PARSE_TIMEGPS)
if (GPSTime::leap_seconds != 0) {
DEBUG_PORT << F("Acquired leap seconds: ") << GPSTime::leap_seconds << '\n';
if (!disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEGPS ))
DEBUG_PORT.println( F("disable TIMEGPS failed!") );
#if defined(UBLOX_PARSE_TIMEUTC)
if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEUTC ))
DEBUG_PORT.println( F("enable TIMEUTC failed!") );
state = GETTING_UTC;
#else
start_running();
#endif
}
#endif
} // get_leap_seconds
//--------------------------
void get_utc()
{
#if defined(GPS_FIX_TIME) & defined(GPS_FIX_DATE) & \
defined(UBLOX_PARSE_TIMEUTC)
lock();
bool safe = is_safe();
NeoGPS::clock_t sow = GPSTime::start_of_week();
NeoGPS::time_t utc = fix().dateTime;
unlock();
if (safe && (sow != 0)) {
DEBUG_PORT << F("Acquired UTC: ") << utc << '\n';
DEBUG_PORT << F("Acquired Start-of-Week: ") << sow << '\n';
start_running();
}
#endif
} // get_utc
//--------------------------
void start_running()
{
bool enabled_msg_with_time = false;
#if defined(UBLOX_PARSE_POSLLH)
if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_POSLLH ))
DEBUG_PORT.println( F("enable POSLLH failed!") );
enabled_msg_with_time = true;
#endif
#if defined(UBLOX_PARSE_PVT)
if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_PVT ))
DEBUG_PORT.println( F("enable PVT failed!") );
enabled_msg_with_time = true;
#endif
#if defined(UBLOX_PARSE_VELNED)
if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_VELNED ))
DEBUG_PORT.println( F("enable VELNED failed!") );
enabled_msg_with_time = true;
#endif
#if defined(UBLOX_PARSE_DOP)
if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_DOP ))
DEBUG_PORT.println( F("enable DOP failed!") );
else
DEBUG_PORT.println( F("enabled DOP.") );
enabled_msg_with_time = true;
#endif
#if defined(UBLOX_PARSE_SVINFO)
if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_SVINFO ))
DEBUG_PORT.println( F("enable SVINFO failed!") );
enabled_msg_with_time = true;
#endif
#if defined(UBLOX_PARSE_TIMEUTC)
#if defined(GPS_FIX_TIME) & defined(GPS_FIX_DATE)
if (enabled_msg_with_time &&
!disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEUTC ))
DEBUG_PORT.println( F("disable TIMEUTC failed!") );
#elif defined(GPS_FIX_TIME) | defined(GPS_FIX_DATE)
// If both aren't defined, we can't convert TOW to UTC,
// so ask for the separate UTC message.
if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEUTC ))
DEBUG_PORT.println( F("enable TIMEUTC failed!") );
#endif
#endif
state = RUNNING;
trace_header( DEBUG_PORT );
} // start_running
//--------------------------
bool running()
{
switch (state) {
case GETTING_STATUS : get_status (); break;
case GETTING_LEAP_SECONDS: get_leap_seconds(); break;
case GETTING_UTC : get_utc (); break;
}
return (state == RUNNING);
} // running
} NEOGPS_PACKED;
// Construct the GPS object and hook it to the appropriate serial device
static MyGPS gps( &gpsPort );
#ifdef NMEAGPS_INTERRUPT_PROCESSING
static void GPSisr( uint8_t c )
{
gps.handle( c );
}
#endif
//--------------------------
static void configNMEA( uint8_t rate )
{
for (uint8_t i=NMEAGPS::NMEA_FIRST_MSG; i<=NMEAGPS::NMEA_LAST_MSG; i++) {
ublox::configNMEA( gps, (NMEAGPS::nmea_msg_t) i, rate );
}
}
//--------------------------
static void disableUBX()
{
gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEGPS );
gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEUTC );
gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_VELNED );
gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_POSLLH );
gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_DOP );
}
//--------------------------
void setup()
{
// Start the normal trace output
DEBUG_PORT.begin(9600);
while (!DEBUG_PORT)
;
DEBUG_PORT.print( F("ublox binary protocol example started.\n") );
DEBUG_PORT << F("fix object size = ") << sizeof(gps.fix()) << '\n';
DEBUG_PORT << F("ubloxGPS object size = ") << sizeof(ubloxGPS) << '\n';
DEBUG_PORT << F("MyGPS object size = ") << sizeof(gps) << '\n';
DEBUG_PORT.println( F("Looking for GPS device on " GPS_PORT_NAME) );
DEBUG_PORT.flush();
// Start the UART for the GPS device
#ifdef NMEAGPS_INTERRUPT_PROCESSING
gpsPort.attachInterrupt( GPSisr );
#endif
gpsPort.begin(9600);
// Turn off the preconfigured NMEA standard messages
configNMEA( 0 );
// Turn off things that may be left on by a previous build
disableUBX();
#if 0
// Test a Neo M8 message -- should be rejected by Neo-6 and Neo7
ublox::cfg_nmea_v1_t test;
test.always_output_pos = false; // invalid or failed
test.output_invalid_pos = false;
test.output_invalid_time= false;
test.output_invalid_date= false;
test.use_GPS_only = false;
test.output_heading = false; // even if frozen
test.__not_used__ = false;
test.nmea_version = ublox::cfg_nmea_v1_t::NMEA_V_4_0;
test.num_sats_per_talker_id = ublox::cfg_nmea_v1_t::SV_PER_TALKERID_UNLIMITED;
test.compatibility_mode = false;
test.considering_mode = true;
test.max_line_length_82 = false;
test.__not_used_1__ = 0;
test.filter_gps = false;
test.filter_sbas = false;
test.__not_used_2__= 0;
test.filter_qzss = false;
test.filter_glonass= false;
test.filter_beidou = false;
test.__not_used_3__= 0;
test.proprietary_sat_numbering = false;
test.main_talker_id = ublox::cfg_nmea_v1_t::MAIN_TALKER_ID_GP;
test.gsv_uses_main_talker_id = true;
test.beidou_talker_id[0] = 'G';
test.beidou_talker_id[1] = 'P';
DEBUG_PORT << F("CFG_NMEA result = ") << gps.send( test );
#endif
while (!gps.running())
if (gps.available( gpsPort ))
gps.read();
}
//--------------------------
void loop()
{
if (gps.available( gpsPort ))
trace_all( DEBUG_PORT, gps, gps.read() );
// If the user types something, reset the message configuration
// back to a normal set of NMEA messages. This makes it
// convenient to switch to another example program that
// expects a typical set of messages. This also saves
// putting those config messages in every other example.
if (DEBUG_PORT.available()) {
do { DEBUG_PORT.read(); } while (DEBUG_PORT.available());
DEBUG_PORT.println( F("Stopping...") );
configNMEA( 1 );
disableUBX();
gpsPort.flush();
gpsPort.end();
DEBUG_PORT.println( F("STOPPED.") );
for (;;);
}
}