#include 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 . // //====================================================================== #include //------------------------------------------------------------ // 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 (;;); }