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

772 lines
24 KiB
C++

#include <NMEAGPS.h>
using namespace NeoGPS;
//======================================================================
// Program: NMEAtest.ino
//
// Prerequisites:
// 1) All NMEA standard messages and Satellite Information
// are enabled.
// 2) All 'gps_fix' members are enabled.
// 3) All validation options are enabled.
//
// Description: This test program uses one GPGGA sentence
// to test the parser's:
// 1) robustness WRT dropped, inserted, and mangled characters
// 2) correctness WRT values extracted from the input stream
//
// Some care in testing must be taken because
// 1) The XOR-style checksum is not very good at catching errors.
// 2) The '*' is a special character for delimiting the CRC. If
// it is changed, a CR/LF will allow the sentence to pass.
//
// '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 <Streamers.h>
//------------------------------------------------------------
// Check that the config files are set up properly
#if !defined(NMEAGPS_PARSE_GGA) | \
!defined(NMEAGPS_PARSE_GLL) | \
!defined(NMEAGPS_PARSE_GSA) | \
!defined(NMEAGPS_PARSE_GST) | \
!defined(NMEAGPS_PARSE_GSV) | \
!defined(NMEAGPS_PARSE_RMC) | \
!defined(NMEAGPS_PARSE_VTG) | \
!defined(NMEAGPS_PARSE_ZDA)
#error NMEAGPS_PARSE_GGA, GLL, GSA, GSV, RMC, VTG and ZDA must be defined in NMEAGPS_cfg.h!
#endif
#ifndef GPS_FIX_DATE
#error GPS_FIX_DATE must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_TIME
#error GPS_FIX_TIME must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_LOCATION
#error GPS_FIX_LOCATION must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_LOCATION_DMS
#error GPS_FIX_LOCATION_DMS must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_ALTITUDE
#error GPS_FIX_ALTITUDE must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_SPEED
#error GPS_FIX_SPEED must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_HEADING
#error GPS_FIX_HEADING must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_SATELLITES
#error GPS_FIX_SATELLITES must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_HDOP
#error GPS_FIX_HDOP must be defined in GPSfix_cfg.h!
#endif
#ifndef GPS_FIX_GEOID_HEIGHT
#error GPS_FIX_GEOID_HEIGHT must be defined in GPSfix_cfg.h!
#endif
static NMEAGPS gps;
//--------------------------
// Example sentences
struct LocVector_t
{
float range;
float bearing;
};
static Location_t AyersRock( -253448688L, 1310324914L );
// -25.3448688,131.0324914
// 2520.692128,S,13101.949484,E
// 25 20' 41.528" S 131 1' 56.969" E
static const LocVector_t NiihauToAyersRock = { 9078.681, 238.33972 };
const char validRMC[] __PROGMEM =
"$GPRMC,092725.00,A,2520.69213,S,13101.94948,E,"
"0.004,77.52,091202,,,A*43\r\n";
//...........................
static Location_t ubloxHQ( 472852369L, 85630763L ); // near Zurich, Switzerland
// 47.2852369, 8.5630763
// 47 17' 6.840" N 008 33' 54.954" E
static const LocVector_t NiihauToUblox = { 12248.67, 8.0625 };
const char validGGA[] __PROGMEM =
"$GPGGA,092725.00,4717.113993,N,00833.915904,E,"
"1,8,1.01,499.6,M,48.0,M,,0*5C\r\n";
//...........................
static Location_t MacchuPicchu( -131628050L, -725455080L );
// -13.162805, -72.545508
// 13.162805,S,72.545508,W
// 13 09' 46.098" S 72 32' 43.830" W
static const LocVector_t NiihauToMacchu = { 10315.93, 103.07306 };
const char validGGA2[] __PROGMEM =
"$GPGGA,162254.00,1309.7683,S,7232.7305,W,1,03,2.36,2430.2,M,-25.6,M,,*7E\r\n";
//...........................
static Location_t DexterMO( 367944050L, -899586550L );
// 36.794405, -89.958655
// 36.794405,N,89.958655,W
// 36 47' 39.858" N 89 57' 31.158" W
static const LocVector_t NiihauToDexter = { 6865.319, 58.85472 };
const char validRMC2[] __PROGMEM =
"$GPRMC,162254.00,A,3647.6643,N,8957.5193,W,0.820,188.36,110706,,,A*49\r\n";
//...........................
static Location_t NiihauHI( 218276210L, -1602448760L );
// 21.827621, -160.244876
// 21.827621,N,160.244876,W
// 21 49' 39.4356" N 160 14' 41.5536 W
static const LocVector_t NiihauToNiihau = { 0.0, 90.0 };
const char validRMC3[] __PROGMEM =
"$GPRMC,235959.99,A,2149.65726,N,16014.69256,W,8.690,359.99,051015,9.47,E,A*26\r\n";
// 218276212L, -1602448757L
// 21 49.65727' N 160 14.69254' W
// 21 49' 39.4362" N 160 14' 41.5524" W
const char validRMC4[] __PROGMEM =
"$GPRMC,235959.99,A,2149.65727,N,16014.69254,W,8.690,359.99,051015,9.47,E,A*25\r\n";
static const LocVector_t NiihauToNiihau2 = { 0.00003812513, 54.31585 };
//...........................
static Location_t JujaKenya( -10934552L, 370261835L );
// -1.0934552, 37.0261835
// 01 05' 36.458" S 037 01' 42.140" E
static const LocVector_t NiihauToJuja = { 17046.24, 318.6483 };
const char validGLL[] __PROGMEM =
"$GNGLL,0105.60764,S,03701.70233,E,225627.00,A,A*6B\r\n";
//--------------------------------
const char mtk1[] __PROGMEM =
"$GPGGA,064951.000,2307.1256,N,12016.4438,E,1,8,0.95,39.9,M,17.8,M,,*63\r\n";
const char mtk2[] __PROGMEM =
"$GPRMC,064951.000,A,2307.1256,N,12016.4438,E,0.03,165.48,260406,3.05,W,A*2C\r\n";
const char mtk3[] __PROGMEM =
"$GPVTG,165.48,T,,M,0.03,N,0.06,K,A*36\r\n";
const char mtk4[] __PROGMEM =
"$GPGSA,A,3,29,21,26,15,18,09,06,10,,,,,2.32,0.95,2.11*00\r\n";
const char mtk5[] __PROGMEM =
"$GPGSV,3,1,09,29,36,029,42,21,46,314,43,26,44,020,43,15,21,321,39*7D\r\n";
const char mtk6[] __PROGMEM =
"$GPGSV,3,2,09,18,26,314,40,09,57,170,44,06,20,229,37,10,26,084,37*77\r\n";
const char mtk7[] __PROGMEM =
"$GPGSV,3,3,09,07,,,26*73\r\n";
const char mtk7a[] __PROGMEM =
"$GLGSV,1,1,4,29,36,029,42,21,46,314,43,26,44,020,43,15,21,321,39*5E\r\n";
const char mtk8[] __PROGMEM =
"$GNGST,082356.00,1.8,,,,1.7,1.3,2.2*60\r\n";
const char mtk9[] __PROGMEM =
"$GNRMC,083559.00,A,4717.11437,N,00833.91522,E,0.004,77.52,091202,,,A,V*33\r\n";
const char mtk10[] __PROGMEM =
"$GNGGA,092725.00,4717.11399,N,00833.91590,E,1,08,1.01,499.6,M,48.0,M,,*45\r\n";
const char mtk11[] __PROGMEM =
"$GLZDA,225627.00,21,09,2015,00,00*70\r\n";
const char fpGGA00[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816900,W,"
"1,8,1.01,499.6,M,48.0,M,,0*49\r\n";
const char fpGGA01[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816901,W,"
"1,8,1.01,499.6,M,48.0,M,,0*48\r\n";
const char fpGGA02[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816902,W,"
"1,8,1.01,499.6,M,48.0,M,,0*4B\r\n";
const char fpGGA03[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816903,W,"
"1,8,1.01,499.6,M,48.0,M,,0*4A\r\n";
const char fpGGA04[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816904,W,"
"1,8,1.01,499.6,M,48.0,M,,0*4D\r\n";
const char fpGGA05[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816905,W,"
"1,8,1.01,499.6,M,48.0,M,,0*4C\r\n";
const char fpGGA06[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816906,W,"
"1,8,1.01,499.6,M,48.0,M,,0*4F\r\n";
const char fpGGA07[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816907,W,"
"1,8,1.01,499.6,M,48.0,M,,0*4E\r\n";
const char fpGGA08[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816908,W,"
"1,8,1.01,499.6,M,48.0,M,,0*41\r\n";
const char fpGGA09[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816909,W,"
"1,8,1.01,499.6,M,48.0,M,,0*40\r\n";
const char fpGGA10[] __PROGMEM = "$GPGGA,092725.00,3242.9000,N,11705.816910,W,"
"1,8,1.01,499.6,M,48.0,M,,0*48\r\n";
//--------------------------
static bool parse_P( const char *ptr )
{
bool decoded = false;
char c;
gps.fix().init();
while ( (c = pgm_read_byte( ptr++ )) != '\0' ) {
if (NMEAGPS::DECODE_COMPLETED == gps.decode( c )) {
decoded = true;
}
}
return decoded;
}
//--------------------------
static void traceSample( const char *ptr, bool init = true )
{
Serial << F("Input: ") << (const __FlashStringHelper *) ptr;
if (init)
gps.data_init();
bool decoded = parse_P( ptr );
if (decoded)
Serial << F("Results: ");
else
Serial << F("Failed to decode! ");
trace_all( Serial, gps, gps.fix() );
Serial << '\n';
}
//--------------------------
static uint8_t passed = 0;
static uint8_t failed = 0;
static void checkFix
( const char *msg, NMEAGPS::nmea_msg_t msg_type, gps_fix::status_t status,
int32_t lat, int32_t lon,
uint8_t latDeg, uint8_t latMin, uint8_t latSec, uint16_t latSecFrac, Hemisphere_t ns,
uint8_t lonDeg, uint8_t lonMin, uint8_t lonSec, uint16_t lonSecFrac, Hemisphere_t ew,
const LocVector_t & to )
{
const char *ptr = msg;
for (;;) {
char c = pgm_read_byte( ptr++ );
if (!c) {
Serial.print( F("FAILED to parse \"") );
Serial.print( (const __FlashStringHelper *) msg );
Serial.println( F("\"\n") );
failed++;
break;
}
if (NMEAGPS::DECODE_COMPLETED == gps.decode( c )) {
bool ok = true;
const gps_fix & fix = gps.fix();
if (gps.nmeaMessage != msg_type) {
Serial.print( F("FAILED wrong message type ") );
Serial.println( gps.nmeaMessage );
failed++;
ok = false;
}
if (fix.status != status ) {
Serial.print( F("FAILED wrong status ") );
Serial.print( fix.status );
Serial.print( F(" (expected ") );
Serial.print( status );
Serial.println( ')' );
failed++;
ok = false;
}
if (fix.latitudeL() != lat) {
Serial.print( F("FAILED wrong latitude ") );
Serial.print( fix.latitudeL() );
Serial.print( F(" (expected ") );
Serial.print( lat );
Serial.println( ')' );
failed++;
ok = false;
}
if (fix.longitudeL() != lon) {
Serial.print( F("FAILED wrong longitude ") );
Serial.print( fix.longitudeL() );
Serial.print( F(" (expected ") );
Serial.print( lon );
Serial.println( ')' );
failed++;
ok = false;
}
if (fix.latitudeDMS.degrees != latDeg) {
Serial.print( F("FAILED wrong latitude degrees ") );
Serial.print( fix.latitudeDMS.degrees );
Serial.print( F(", expected ") );
Serial.println( latDeg );
failed++;
ok = false;
}
if (fix.latitudeDMS.minutes != latMin) {
Serial.print( F("FAILED wrong latitude minutes ") );
Serial.print( fix.latitudeDMS.minutes );
Serial.print( F(", expected ") );
Serial.println( latMin );
failed++;
ok = false;
}
if (fix.latitudeDMS.seconds_whole != latSec) {
Serial.print( F("FAILED wrong latitude seconds ") );
Serial.print( fix.latitudeDMS.seconds_whole );
Serial.print( F(", expected ") );
Serial.println( latSec );
failed++;
ok = false;
}
int8_t fracDiff = (int8_t)(fix.latitudeDMS.seconds_frac - latSecFrac);
const int8_t ieps = 1;
if (abs(fracDiff) > ieps) {
Serial.print( F("FAILED wrong latitude seconds fraction ") );
Serial.print( fix.latitudeDMS.seconds_frac );
Serial.print( F(", expected ") );
Serial.println( latSecFrac );
failed++;
ok = false;
}
if (fix.latitudeDMS.hemisphere != ns) {
Serial.print( F("FAILED wrong latitude NS ") );
Serial.println( fix.latitudeDMS.NS() );
failed++;
ok = false;
}
if (fix.longitudeDMS.degrees != lonDeg) {
Serial.print( F("FAILED wrong longitude degrees ") );
Serial.print( fix.longitudeDMS.degrees );
Serial.print( F(", expected ") );
Serial.println( lonDeg );
failed++;
ok = false;
}
if (fix.longitudeDMS.minutes != lonMin) {
Serial.print( F("FAILED wrong longitude minutes ") );
Serial.print( fix.longitudeDMS.minutes );
Serial.print( F(", expected ") );
Serial.println( lonMin );
failed++;
ok = false;
}
if (fix.longitudeDMS.seconds_whole != lonSec) {
Serial.print( F("FAILED wrong longitude seconds ") );
Serial.print( fix.longitudeDMS.seconds_whole );
Serial.print( F(", expected ") );
Serial.println( lonSec );
failed++;
ok = false;
}
fracDiff = (int8_t)(fix.longitudeDMS.seconds_frac - lonSecFrac);
if (abs(fracDiff) > ieps) {
Serial.print( F("FAILED wrong longitude seconds fraction ") );
Serial.print( fix.longitudeDMS.seconds_frac );
Serial.print( F(", expected ") );
Serial.println( lonSecFrac );
failed++;
ok = false;
}
if (fix.longitudeDMS.hemisphere != ew) {
Serial.print( F("FAILED wrong longitude EW ") );
Serial.println( fix.longitudeDMS.EW() );
failed++;
ok = false;
}
char floatChars[16];
float distance = NiihauHI.DistanceKm( fix.location );
float diff = abs( distance - to.range );
if ( (diff/to.range) > 0.000001 ) {
Serial.print( F("FAILED distance ") );
dtostre( distance, floatChars, 6, DTOSTR_PLUS_SIGN );
Serial.print( floatChars );
Serial.print( F(" != ") );
dtostre( to.range, floatChars, 6, DTOSTR_PLUS_SIGN );
Serial.println( floatChars );
failed++;
ok = false;
}
float courseTo = NiihauHI.BearingToDegrees( fix.location );
diff = abs( courseTo - to.bearing );
if ( diff > 0.005 ) {
Serial.print( F("FAILED bearing ") );
dtostre( courseTo, floatChars, 6, DTOSTR_PLUS_SIGN );
Serial.print( floatChars );
Serial.print( F(" != ") );
dtostre( to.bearing, floatChars, 6, DTOSTR_PLUS_SIGN );
Serial.print( floatChars );
failed++;
ok = false;
}
if (ok)
passed++;
break;
}
}
}
//--------------------------
void setup()
{
// Start the normal trace output
Serial.begin(9600);
Serial.print( F("NMEA test: started\n") );
Serial.print( F("fix object size = ") );
Serial.println( sizeof(gps_fix) );
Serial.print( F("gps object size = ") );
Serial.println( sizeof(NMEAGPS) );
// Some basic rejection tests
Serial.println( F("Test rejection of all byte values") );
for (uint16_t c=0; c < 256; c++) {
if (c != '$') {
if (NMEAGPS::DECODE_CHR_INVALID != gps.decode( (char)c )) {
Serial.print( F("FAILED to reject single character ") );
Serial.println( c );
failed++;
return;
}
}
}
passed++;
Serial.println( F("Test rejection of multiple $") );
for (uint16_t i=0; i < 256; i++) {
if (NMEAGPS::DECODE_COMPLETED == gps.decode( '$' )) {
Serial.print( F("FAILED to reject multiple '$' characters\n") );
failed++;
return;
}
}
passed++;
uint16_t validGGA_len = 0;
// Insert a ' ' at each position of the test sentence
Serial.println( F("Insert ' '") );
uint16_t insert_at = 1;
do {
const char *ptr = validGGA;
uint8_t j = 0;
for (;;) {
if (j++ == insert_at) {
NMEAGPS::decode_t result = gps.decode( ' ' );
if (gps.validateChars() || gps.validateFields()) {
if (result == NMEAGPS::DECODE_COMPLETED) {
Serial.print( F("FAILED incorrectly decoded ' ' @ pos ") );
Serial.println( insert_at );
failed++;
} else if (gps.nmeaMessage != NMEAGPS::NMEA_UNKNOWN) {
Serial.print( F("FAILED incorrectly accepted ' ' @ pos ") );
Serial.println( insert_at );
failed++;
}
}
}
char c = pgm_read_byte( ptr++ );
if (!c) {
if (validGGA_len == 0) {
validGGA_len = j-1;
Serial.print( F("Test string length = ") );
Serial.println( validGGA_len );
}
break;
}
if (gps.decode( c ) == NMEAGPS::DECODE_COMPLETED) {
Serial.print( F("FAILED incorrectly decoded @ pos ") );
Serial.println( insert_at );
failed++;
//return;
}
}
} while (++insert_at < validGGA_len-2);
passed++;
// Drop one character from each position in example sentence
Serial.println( F("Drop character") );
for (uint16_t i=0; i < validGGA_len-3; i++) {
const char *ptr = validGGA;
uint8_t firstInvalidPos = 0;
char dropped = 0;
for (uint8_t j = 0;; j++) {
char c = pgm_read_byte( ptr++ );
if (!c || (c == '*')) break;
if (j == i) {
dropped = c;
} else {
NMEAGPS::decode_t result = gps.decode( c );
if (result == NMEAGPS::DECODE_COMPLETED) {
Serial.print( F("FAILED decoded after dropping '") );
Serial << dropped;
Serial.print( F("' at pos ") );
Serial.println( i );
failed++;
} else if (gps.nmeaMessage == NMEAGPS::NMEA_UNKNOWN) {
if (firstInvalidPos != 0)
firstInvalidPos = j;
}
}
}
if (firstInvalidPos != 0) {
Serial.print( F(" /*") );
Serial.print( i );
Serial.print( F("*/ ") );
Serial.println( firstInvalidPos );
}
}
passed++;
// Mangle one character from each position in example sentence
Serial.println( F("Mangle one character") );
for (uint16_t i=0; i < validGGA_len-3; i++) {
const char *ptr = validGGA;
uint8_t j = 0;
char replaced = 0;
for (;;) {
char c = pgm_read_byte( ptr++ );
if (!c || (c == '*')) break;
if (j++ == i)
replaced = c++; // mangle means increment
if (NMEAGPS::DECODE_COMPLETED == gps.decode( c )) {
Serial.print( F("FAILED replacing '") );
Serial << (uint8_t) replaced;
Serial.print( F("' with '") );
Serial << (uint8_t) (replaced+1);
Serial.print( F("' at pos ") );
Serial.println( i );
failed++;
break;
//return;
}
}
}
passed++;
// Verify that exact values are extracted
Serial.println( F("Verify parsed values") );
{
const char *ptr = validGGA;
for (;;) {
char c = pgm_read_byte( ptr++ );
if (!c) {
Serial.print( F("FAILED to parse \"") );
Serial.print( (str_P) validGGA );
Serial.println( F("\"\n") );
failed++;
break;
}
if (NMEAGPS::DECODE_COMPLETED == gps.decode( c )) {
gps_fix expected;
expected.dateTime.parse( PSTR("2002-12-09 09:27:25") );
expected.dateTime_cs = 0;
if (gps.nmeaMessage != NMEAGPS::NMEA_GGA) {
Serial.print( F("FAILED wrong message type ") );
Serial.println( gps.nmeaMessage );
failed++;
break;
}
if ((gps.fix().dateTime.hours != expected.dateTime.hours ) ||
(gps.fix().dateTime.minutes != expected.dateTime.minutes) ||
(gps.fix().dateTime.seconds != expected.dateTime.seconds) ||
(gps.fix().dateTime_cs != expected.dateTime_cs)) {
Serial << F("FAILED wrong time ") << gps.fix().dateTime << '.' << gps.fix().dateTime_cs << F(" != ") << expected.dateTime << '.' << expected.dateTime_cs << '\n';
failed++;
break;
}
if (gps.fix().latitudeL() != 472852332L) {
Serial.print( F("FAILED wrong latitude ") );
Serial.println( gps.fix().latitudeL() );
failed++;
break;
}
if (gps.fix().longitudeL() != 85652651L) {
Serial.print( F("FAILED wrong longitude ") );
Serial.println( gps.fix().longitudeL() );
failed++;
break;
}
if (gps.fix().status != gps_fix::STATUS_STD) {
Serial.print( F("FAILED wrong status ") );
Serial.println( gps.fix().status );
failed++;
break;
}
if (gps.fix().satellites != 8) {
Serial.print( F("FAILED wrong satellites ") );
Serial.println( gps.fix().satellites );
failed++;
break;
}
if (gps.fix().hdop != 1010) {
Serial.print( F("FAILED wrong HDOP ") );
Serial.println( gps.fix().hdop );
failed++;
break;
}
if (gps.fix().altitude_cm() != 49960) {
Serial.print( F("FAILED wrong altitude ") );
Serial.println( gps.fix().longitudeL() );
failed++;
break;
}
break;
}
}
}
passed++;
checkFix( validRMC , NMEAGPS::NMEA_RMC, gps_fix::STATUS_STD,
-253448688L, 1310324913L,
25, 20, 41, 528, SOUTH_H, 131, 1, 56, 969, EAST_H,
NiihauToAyersRock );
checkFix( validGGA , NMEAGPS::NMEA_GGA, gps_fix::STATUS_STD,
472852332L, 85652651L,
47, 17, 6, 840, NORTH_H, 8, 33, 54, 954, EAST_H,
NiihauToUblox );
if (gps.fix().geoidHeight_cm() != 4800) {
Serial.print( F("FAILED wrong geoid height for 48.00") );
Serial.println( gps.fix().geoidHeight_cm() );
failed++;
}
checkFix( validGGA2, NMEAGPS::NMEA_GGA, gps_fix::STATUS_STD,
-131628050L, -725455083L,
13, 9, 46, 98, SOUTH_H, 72, 32, 43, 830, WEST_H,
NiihauToMacchu );
if (gps.fix().geoidHeight_cm() != -2560) {
Serial.print( F("FAILED wrong geoid height for -25.60") );
Serial.println( gps.fix().geoidHeight_cm() );
failed++;
}
checkFix( validRMC2, NMEAGPS::NMEA_RMC, gps_fix::STATUS_STD,
367944050L, -899586550L,
36, 47, 39, 858, NORTH_H, 89, 57, 31, 158, WEST_H,
NiihauToDexter );
checkFix( validRMC3, NMEAGPS::NMEA_RMC, gps_fix::STATUS_STD,
218276210L, -1602448760L,
21, 49, 39, 436, NORTH_H, 160, 14, 41, 554, WEST_H,
NiihauToNiihau );
checkFix( validRMC4, NMEAGPS::NMEA_RMC, gps_fix::STATUS_STD,
218276212L, -1602448757L,
21, 49, 39, 436, NORTH_H, 160, 14, 41, 552, WEST_H,
NiihauToNiihau2 );
checkFix( validGLL , NMEAGPS::NMEA_GLL, gps_fix::STATUS_STD,
-10934607L, 370283722L,
1, 5, 36, 458, SOUTH_H, 37, 1, 42, 140, EAST_H,
NiihauToJuja );
}
//--------------------------
void loop()
{
Serial.print( F("PASSED ") );
Serial << passed;
Serial.println( F(" tests.") );
if (failed) {
Serial.print( F("FAILED ") );
Serial << failed;
Serial.println( F(" tests.") );
} else {
Serial << F("------ Samples ------\nResults format:\n ");
trace_header( Serial );
Serial << '\n';
#ifdef NMEAGPS_STATS
gps.statistics.init();
#endif
traceSample( validGGA );
traceSample( validGGA2 );
traceSample( validRMC );
traceSample( validRMC2 );
traceSample( validRMC3 );
traceSample( validGLL );
traceSample( mtk1 );
traceSample( mtk2 );
traceSample( mtk3 );
traceSample( mtk4 );
traceSample( mtk5 );
traceSample( mtk6, false );
traceSample( mtk7, false );
traceSample( mtk7a, false );
traceSample( mtk8 );
traceSample( mtk9 );
traceSample( mtk10 );
traceSample( mtk11 );
if (!gps.fix().valid.date ||
(gps.fix().dateTime.date != 21) ||
(gps.fix().dateTime.month != 9) ||
(gps.fix().dateTime.year != 15) ||
!gps.fix().valid.time ||
(gps.fix().dateTime.hours != 22) ||
(gps.fix().dateTime.minutes != 56) ||
(gps.fix().dateTime.seconds != 27))
Serial << F("******** ZDA not parsed correctly **********\n");
/**
* This next section displays incremental longitudes.
* If you have defined USE_FLOAT in Streamers.cpp, this will show
* how the conversion to /float/ causes loss of accuracy compared
* to the /uint32_t/ values.
*/
Serial << F("--- floating point conversion tests ---\n\n");
traceSample( fpGGA00 );
traceSample( fpGGA01 );
traceSample( fpGGA02 );
traceSample( fpGGA03 );
traceSample( fpGGA04 );
traceSample( fpGGA05 );
traceSample( fpGGA06 );
traceSample( fpGGA07 );
traceSample( fpGGA08 );
traceSample( fpGGA09 );
traceSample( fpGGA10 );
}
for (;;);
}