@@ -278,7 +278,7 @@ bool UM980::isConnected()
278278// If isBlocking is true, external consumers should not read/write to the Serial hardware
279279bool UM980::isBlocking ()
280280{
281- return (unicoreLibrarySemaphoreBlock);
281+ return (unicoreLibrarySemaphoreBlock);
282282}
283283
284284// Calling this function with nothing sets the debug port to Serial
@@ -430,8 +430,8 @@ void um980ProcessMessage(SEMP_PARSE_STATE *parse, uint16_t type)
430430 switch (type)
431431 {
432432 case UM980_NMEA_PARSER_INDEX:
433- ptrUM980->debugPrintf (" Unicore Lib: Valid NMEA Sentence: %s, 0x%04x (%d) bytes" , sempNmeaGetSentenceName (parse),
434- parse->length , parse->length );
433+ ptrUM980->debugPrintf (" Unicore Lib: Valid NMEA Sentence: %s, 0x%04x (%d) bytes" ,
434+ sempNmeaGetSentenceName (parse), parse->length , parse->length );
435435 break ;
436436
437437 case UM980_UNICORE_HASH_PARSER_INDEX:
@@ -444,7 +444,8 @@ void um980ProcessMessage(SEMP_PARSE_STATE *parse, uint16_t type)
444444 break ;
445445
446446 case UM980_UNICORE_BINARY_PARSER_INDEX:
447- ptrUM980->debugPrintf (" Unicore Lib: Valid Unicore message: 0x%04x (%d) bytes" , parse->length , parse->length );
447+ ptrUM980->debugPrintf (" Unicore Lib: Valid Unicore message: 0x%04x (%d) bytes" , parse->length ,
448+ parse->length );
448449 break ;
449450 }
450451 }
@@ -473,13 +474,23 @@ void um980ProcessMessage(SEMP_PARSE_STATE *parse, uint16_t type)
473474 break ;
474475
475476 case UM980_NMEA_PARSER_INDEX:
476- // $command,MODE,response: OK*5D
477+
478+ // Is this a NMEA response or command response?
479+
477480 if (strcasecmp ((char *)scratchPad->nmea .sentenceName , " command" ) != 0 &&
478481 strcasecmp ((char *)scratchPad->nmea .sentenceName , " MASK" ) != 0 &&
479- strcasecmp ((char *)scratchPad->nmea .sentenceName , " CONFIG" ) != 0 ) // Found
482+ strcasecmp ((char *)scratchPad->nmea .sentenceName , " CONFIG" ) != 0 )
483+ {
484+ // command, MASK, CONFIG not found
485+
486+ if (strcasecmp ((char *)scratchPad->nmea .sentenceName , " GNGGA" ) == 0 )
487+ {
488+ ptrUM980->debugPrintf (" um980ProcessMessage GNGGA" );
489+ }
480490
481491 // Unknown response, ignore this message
482492 ptrUM980->debugPrintf (" Unicore Lib: Message ignored: %s" , parse->buffer );
493+ }
483494 else
484495 {
485496 // Does this response contain the command we are looking for?
@@ -1154,7 +1165,7 @@ void UM980::unicoreHandler(uint8_t *response, uint16_t length)
11541165 }
11551166 else if (messageID == messageIdBestnavXyz)
11561167 {
1157- // debugPrintf("BestNavXyz Handler");
1168+ debugPrintf (" BestNavXyz Handler" );
11581169 CHECK_POINTER_VOID (packetBESTNAVXYZ, initBestnavXyz); // Check that RAM has been allocated
11591170
11601171 lastUpdateEcef = millis (); // Update stale marker
@@ -1172,7 +1183,7 @@ void UM980::unicoreHandler(uint8_t *response, uint16_t length)
11721183 }
11731184 else if (messageID == messageIdVersion)
11741185 {
1175- // debugPrintf("Version Handler");
1186+ debugPrintf (" Version Handler" );
11761187 CHECK_POINTER_VOID (packetVERSION, initVersion); // Check that RAM has been allocated
11771188
11781189 lastUpdateVersion = millis (); // Update stale marker
@@ -1188,7 +1199,48 @@ void UM980::unicoreHandler(uint8_t *response, uint16_t length)
11881199 }
11891200 else
11901201 {
1191- debugPrintf (" Unknown message id: %d\r\n " , messageID);
1202+ // Is this a NMEA sentence?
1203+ if (response[0 ] == ' $' )
1204+ {
1205+ response[length] = ' \0 ' ; // Force terminator because strncasestr does not exist
1206+
1207+ // The UM980 does not respond to binary requests when there is no GNSS reception.
1208+ // Block BestNavB, etc commands if there is no fix.
1209+ // Look for GNGGA NMEA then extract GNSS position status (spot 6).
1210+ // $GNGGA,181535.00,,,,,0,00,9999.0,,,,,,*43
1211+ char *responsePointer = strcasestr ((char *)response, " GNGGA" );
1212+ if (responsePointer != nullptr ) // Found
1213+ {
1214+ char gngga[100 ];
1215+ strncpy (gngga, (const char *)response, length); // Make copy before strtok
1216+
1217+ debugPrintf (" Unicore Lib: GNGGA message: %s\r\n " , gngga);
1218+
1219+ char *pt;
1220+ pt = strtok (gngga, " ," );
1221+ int counter = 0 ;
1222+ while (pt != NULL )
1223+ {
1224+ int spotValue = atoi (pt);
1225+ // Serial.printf("counter: %d spot: %s spotvalue: %d\r\n", counter, pt, spotValue);
1226+ if (counter++ == 6 )
1227+ {
1228+ nmeaPositionStatus = spotValue;
1229+ debugPrintf (" nmeaPositionStatus: %d\r\n " , nmeaPositionStatus);
1230+ }
1231+ pt = strtok (NULL , " ," );
1232+ }
1233+ }
1234+ else
1235+ {
1236+ // Unhandled NMEA message
1237+ // debugPrintf("Unicore Lib: Unhandled NMEA sentence (%d bytes): %s\r\n", length, (char *)response);
1238+ }
1239+ }
1240+ else
1241+ {
1242+ debugPrintf (" Unicore Lib: Unknown message id: %d\r\n " , messageID);
1243+ }
11921244 }
11931245}
11941246
@@ -1238,6 +1290,19 @@ bool UM980::initVersion()
12381290// Allocate RAM for packetBESTNAV and initialize it
12391291bool UM980::initBestnav (uint8_t rate)
12401292{
1293+ if ((startBinaryBeforeFix == false ) && (isNmeaFixed () == false ))
1294+ {
1295+ debugPrintf (" Unicore Lib: BestNav no fix" );
1296+ return (false );
1297+ }
1298+ else
1299+ {
1300+ if (startBinaryBeforeFix == true )
1301+ Serial.println (" startBinaryBeforeFix is true" );
1302+ if (isNmeaFixed () == true )
1303+ Serial.println (" isNmeaFixed() is true" );
1304+ }
1305+
12411306 packetBESTNAV = new UNICORE_BESTNAV_t; // Allocate RAM for the main struct
12421307 if (packetBESTNAV == nullptr )
12431308 {
@@ -1283,6 +1348,12 @@ bool UM980::initBestnav(uint8_t rate)
12831348// Allocate RAM for packetBESTNAVXYZ and initialize it
12841349bool UM980::initBestnavXyz (uint8_t rate)
12851350{
1351+ if ((startBinaryBeforeFix == false ) && (isNmeaFixed () == false ))
1352+ {
1353+ debugPrintf (" Unicore Lib: BestNavXyz no fix" );
1354+ return (false );
1355+ }
1356+
12861357 packetBESTNAVXYZ = new UNICORE_BESTNAVXYZ_t; // Allocate RAM for the main struct
12871358 if (packetBESTNAVXYZ == nullptr )
12881359 {
@@ -1328,6 +1399,12 @@ bool UM980::initBestnavXyz(uint8_t rate)
13281399// Allocate RAM for packetRECTIME and initialize it
13291400bool UM980::initRectime (uint8_t rate)
13301401{
1402+ if ((startBinaryBeforeFix == false ) && (isNmeaFixed () == false ))
1403+ {
1404+ debugPrintf (" Unicore Lib: RecTime no fix" );
1405+ return (false );
1406+ }
1407+
13311408 packetRECTIME = new UNICORE_RECTIME_t; // Allocate RAM for the main struct
13321409 if (packetRECTIME == nullptr )
13331410 {
@@ -1618,3 +1695,24 @@ char *UM980::getVersionFull(uint16_t maxWaitMs)
16181695 return ((char *)" Error1" );
16191696 return ((char *)" Error2" );
16201697}
1698+
1699+ // Returns true when GNGGA NMEA reports position status >= 2
1700+ bool UM980::isNmeaFixed ()
1701+ {
1702+ if (nmeaPositionStatus >= 2 )
1703+ return (true );
1704+ return (false );
1705+ }
1706+
1707+ // By default, library will attempt to start RECTIME and BESTNAV regardless of GNSS fix
1708+ // This may lead to command timeouts as the UM980 does not appear to respond to BESTNAVB commands if 3D fix is not
1709+ // achieved. Set startBinartBeforeFix = false via disableBinaryBeforeFix() to block binary commands before a fix is
1710+ // achieved
1711+ void UM980::enableBinaryBeforeFix ()
1712+ {
1713+ startBinaryBeforeFix = true ;
1714+ }
1715+ void UM980::disableBinaryBeforeFix ()
1716+ {
1717+ startBinaryBeforeFix = false ;
1718+ }
0 commit comments