Skip to content

Commit d2c714f

Browse files
authored
Merge pull request #50 from sparkfun/release_candidate
v3.1.3 - add full support for NAV-SIG - change NEO-F10N example to NAV-SIG
2 parents 7ceb69b + 0396f45 commit d2c714f

File tree

6 files changed

+355
-16
lines changed

6 files changed

+355
-16
lines changed

examples/NEO-F10N/Example1_RAWX/Example1_RAWX.ino renamed to examples/NEO-F10N/Example1_NAV_SIG/Example1_NAV_SIG.ino

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
/*
2-
Configuring the NEO-F10N GNSS to send RXM RAWX reports over Serial and display them using a callback
2+
Configuring the NEO-F10N GNSS to send NAV SIG reports over Serial and display them using a callback
33
By: Paul Clark
44
SparkFun Electronics
5-
Date: November 24th, 2023
5+
Date: February 29th, 2024
66
License: MIT. See license file for more information.
77
8-
This example shows how to configure the u-blox NEO-F10N GNSS to send RXM RAWX reports automatically
8+
This example shows how to configure the u-blox NEO-F10N GNSS to send NAV SIG reports automatically
99
and access the data via a callback. It also demonstrates how to mark the L5 signals as healthy.
1010
1111
Note: the NEO-F10N only supports UART1. It does not support I2C, SPI or built-in USB.
1212
To run this example on the SparkFun NEO-F10N breakout, you need to open the USB-TX and USB-RX jumpers
1313
to isolate the on-board CH340 USB interface chip. See Hardware Connections below.
1414
15-
Note: the engineering sample of the NEO-F10N-00B supports RXM-RAWX. Production firmware may not.
16-
1715
Feel like supporting open source hardware?
1816
Buy a board from SparkFun!
1917
NEO-F10N: https://www.sparkfun.com/products/24114
@@ -32,22 +30,22 @@
3230
#include <SparkFun_u-blox_GNSS_v3.h> //http://librarymanager/All#SparkFun_u-blox_GNSS_v3
3331
SFE_UBLOX_GNSS_SERIAL myGNSS;
3432

35-
// Callback: newRAWX will be called when new RXM RAWX data arrives
36-
// See u-blox_structs.h for the full definition of UBX_RXMRAWX_data_t
37-
// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMRAWXcallback
38-
// / _____ This _must_ be UBX_RXM_RAWX_data_t
33+
// Callback: newSIG will be called when new NAV SIG data arrives
34+
// See u-blox_structs.h for the full definition of UBX_NAV_SIG_data_t
35+
// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSIGcallback
36+
// / _____ This _must_ be UBX_NAV_SIG_data_t
3937
// | / _____ You can use any name you like for the struct
4038
// | | /
4139
// | | |
42-
void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct)
40+
void newSIG(UBX_NAV_SIG_data_t *ubxDataStruct)
4341
{
4442
Serial.println();
4543

46-
Serial.print(F("New RAWX data received. It contains "));
47-
Serial.print(ubxDataStruct->header.numMeas); // Print numMeas (Number of measurements / blocks)
44+
Serial.print(F("New NAV SIG data received. It contains "));
45+
Serial.print(ubxDataStruct->header.numSigs); // Print numSigs (Number of signals / blocks)
4846
Serial.println(F(" data blocks:"));
4947

50-
for (uint8_t block = 0; block < ubxDataStruct->header.numMeas; block++) // For each block
48+
for (uint8_t block = 0; block < ubxDataStruct->header.numSigs; block++) // For each block
5149
{
5250
char SV[14 + 4 + 4 + 256 + 1]; // Allocate space for sigId plus svId plus cno plus bars plus NULL
5351
switch (ubxDataStruct->blocks[block].gnssId)
@@ -274,7 +272,7 @@ void setup()
274272
myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART1 port to output UBX only (turn off NMEA noise)
275273
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
276274

277-
myGNSS.setMeasurementRate(5000); //Produce one solution every five seconds (RAWX produces a _lot_ of data!)
275+
myGNSS.setMeasurementRate(5000); //Produce one solution every five seconds (NAV SIG produces a _lot_ of data!)
278276

279277
myGNSS.setVal8(UBLOX_CFG_SIGNAL_GPS_L5_ENA, 1); // Make sure the GPS L5 band is enabled (needed on the NEO-F9P)
280278

@@ -284,7 +282,7 @@ void setup()
284282

285283
myGNSS.softwareResetGNSSOnly(); // Restart the GNSS to apply the L5 health override
286284

287-
myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX
285+
myGNSS.setAutoNAVSIGcallbackPtr(&newSIG); // Enable automatic NAV SIG messages with callback to newSIG
288286
}
289287

290288
void loop()

keywords.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ UBX_NAV_PVAT_data_t KEYWORD1
4545
UBX_NAV_TIMEUTC_data_t KEYWORD1
4646
UBX_NAV_CLOCK_data_t KEYWORD1
4747
UBX_NAV_SAT_data_t KEYWORD1
48+
UBX_NAV_SIG_data_t KEYWORD1
4849
UBX_NAV_SVIN_data_t KEYWORD1
4950
UBX_NAV_RELPOSNED_data_t KEYWORD1
5051
UBX_NAV_TIMELS_data_t KEYWORD1
@@ -441,6 +442,15 @@ assumeAutoNAVSAT KEYWORD2
441442
flushNAVSAT KEYWORD2
442443
logNAVSAT KEYWORD2
443444

445+
getNAVSIG KEYWORD2
446+
setAutoNAVSIG KEYWORD2
447+
setAutoNAVSIGrate KEYWORD2
448+
setAutoNAVSIGcallback KEYWORD2
449+
setAutoNAVSIGcallbackPtr KEYWORD2
450+
assumeAutoNAVSIG KEYWORD2
451+
flushNAVSIG KEYWORD2
452+
logNAVSIG KEYWORD2
453+
444454
getRELPOSNED KEYWORD2
445455
setAutoRELPOSNED KEYWORD2
446456
setAutoRELPOSNEDrate KEYWORD2
@@ -923,6 +933,7 @@ UBX_NAV_PVAT LITERAL1
923933
UBX_NAV_RELPOSNED LITERAL1
924934
UBX_NAV_RESETODO LITERAL1
925935
UBX_NAV_SAT LITERAL1
936+
UBX_NAV_SIG LITERAL1
926937
UBX_NAV_SBAS LITERAL1
927938
UBX_NAV_SIG LITERAL1
928939
UBX_NAV_SLAS LITERAL1

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=SparkFun u-blox GNSS v3
2-
version=3.1.2
2+
version=3.1.3
33
author=SparkFun Electronics <[email protected]>
44
maintainer=SparkFun Electronics <sparkfun.com>
55
sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules<br/><br/>

src/u-blox_GNSS.cpp

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,16 @@ void DevUBLOXGNSS::end(void)
329329
packetUBXNAVSAT = nullptr;
330330
}
331331

332+
if (packetUBXNAVSIG != nullptr)
333+
{
334+
if (packetUBXNAVSIG->callbackData != nullptr)
335+
{
336+
delete packetUBXNAVSIG->callbackData;
337+
}
338+
delete packetUBXNAVSIG;
339+
packetUBXNAVSIG = nullptr;
340+
}
341+
332342
if (packetUBXRXMPMP != nullptr)
333343
{
334344
if (packetUBXRXMPMP->callbackData != nullptr)
@@ -1409,6 +1419,12 @@ bool DevUBLOXGNSS::autoLookup(uint8_t Class, uint8_t ID, uint16_t *maxSize)
14091419
*maxSize = UBX_NAV_SAT_MAX_LEN;
14101420
return (packetUBXNAVSAT != nullptr);
14111421
}
1422+
else if (ID == UBX_NAV_SIG)
1423+
{
1424+
if (maxSize != nullptr)
1425+
*maxSize = UBX_NAV_SIG_MAX_LEN;
1426+
return (packetUBXNAVSIG != nullptr);
1427+
}
14121428
#endif
14131429
break;
14141430
case UBX_CLASS_RXM:
@@ -3868,6 +3884,49 @@ void DevUBLOXGNSS::processUBXpacket(ubxPacket *msg)
38683884
}
38693885
}
38703886
}
3887+
else if (msg->id == UBX_NAV_SIG) // Note: length is variable
3888+
{
3889+
// Parse various byte fields into storage - but only if we have memory allocated for it
3890+
if (packetUBXNAVSIG != nullptr)
3891+
{
3892+
packetUBXNAVSIG->data.header.iTOW = extractLong(msg, 0);
3893+
packetUBXNAVSIG->data.header.version = extractByte(msg, 4);
3894+
packetUBXNAVSIG->data.header.numSigs = extractByte(msg, 5);
3895+
3896+
// The NAV SIG message could potentially contain data for 255 signals. (numSigs is uint8_t. UBX_NAV_SIG_MAX_BLOCKS is 92)
3897+
for (uint16_t i = 0; (i < UBX_NAV_SIG_MAX_BLOCKS) && (i < ((uint16_t)packetUBXNAVSIG->data.header.numSigs)) && ((i * 16) < (msg->len - 8)); i++)
3898+
{
3899+
uint16_t offset = (i * 16) + 8;
3900+
packetUBXNAVSIG->data.blocks[i].gnssId = extractByte(msg, offset + 0);
3901+
packetUBXNAVSIG->data.blocks[i].svId = extractByte(msg, offset + 1);
3902+
packetUBXNAVSIG->data.blocks[i].sigId = extractByte(msg, offset + 2);
3903+
packetUBXNAVSIG->data.blocks[i].freqId = extractByte(msg, offset + 3);
3904+
packetUBXNAVSIG->data.blocks[i].prRes = extractSignedInt(msg, offset + 4);
3905+
packetUBXNAVSIG->data.blocks[i].cno = extractByte(msg, offset + 6);
3906+
packetUBXNAVSIG->data.blocks[i].qualityInd = extractByte(msg, offset + 7);
3907+
packetUBXNAVSIG->data.blocks[i].corrSource = extractByte(msg, offset + 8);
3908+
packetUBXNAVSIG->data.blocks[i].ionoModel = extractByte(msg, offset + 9);
3909+
packetUBXNAVSIG->data.blocks[i].sigFlags.all = extractInt(msg, offset + 10);
3910+
}
3911+
3912+
// Mark all datums as fresh (not read before)
3913+
packetUBXNAVSIG->moduleQueried = true;
3914+
3915+
// Check if we need to copy the data for the callback
3916+
if ((packetUBXNAVSIG->callbackData != nullptr) // If RAM has been allocated for the copy of the data
3917+
&& (packetUBXNAVSIG->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale
3918+
{
3919+
memcpy(&packetUBXNAVSIG->callbackData->header.iTOW, &packetUBXNAVSIG->data.header.iTOW, sizeof(UBX_NAV_SIG_data_t));
3920+
packetUBXNAVSIG->automaticFlags.flags.bits.callbackCopyValid = true;
3921+
}
3922+
3923+
// Check if we need to copy the data into the file buffer
3924+
if (packetUBXNAVSIG->automaticFlags.flags.bits.addToFileBuffer)
3925+
{
3926+
addedToFileBuffer = storePacket(msg);
3927+
}
3928+
}
3929+
}
38713930
#endif
38723931
else if (msg->id == UBX_NAV_RELPOSNED && ((msg->len == UBX_NAV_RELPOSNED_LEN) || (msg->len == UBX_NAV_RELPOSNED_LEN_F9)))
38733932
{
@@ -5747,6 +5806,17 @@ void DevUBLOXGNSS::checkCallbacks(void)
57475806
}
57485807
packetUBXNAVSAT->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale
57495808
}
5809+
5810+
if (packetUBXNAVSIG != nullptr) // If RAM has been allocated for message storage
5811+
if (packetUBXNAVSIG->callbackData != nullptr) // If RAM has been allocated for the copy of the data
5812+
if (packetUBXNAVSIG->automaticFlags.flags.bits.callbackCopyValid == true) // If the copy of the data is valid
5813+
{
5814+
if (packetUBXNAVSIG->callbackPointerPtr != nullptr) // If the pointer to the callback has been defined
5815+
{
5816+
packetUBXNAVSIG->callbackPointerPtr(packetUBXNAVSIG->callbackData); // Call the callback
5817+
}
5818+
packetUBXNAVSIG->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale
5819+
}
57505820
#endif
57515821

57525822
if (packetUBXNAVRELPOSNED != nullptr) // If RAM has been allocated for message storage
@@ -12958,6 +13028,177 @@ void DevUBLOXGNSS::logNAVSAT(bool enabled)
1295813028
return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
1295913029
packetUBXNAVSAT->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled;
1296013030
}
13031+
13032+
// ***** NAV SIG automatic support
13033+
13034+
// Signal information
13035+
// Returns true if commands was successful
13036+
bool DevUBLOXGNSS::getNAVSIG(uint16_t maxWait)
13037+
{
13038+
if (packetUBXNAVSIG == nullptr)
13039+
initPacketUBXNAVSIG(); // Check that RAM has been allocated for the NAVSIG data
13040+
if (packetUBXNAVSIG == nullptr) // Bail if the RAM allocation failed
13041+
return (false);
13042+
13043+
if (packetUBXNAVSIG->automaticFlags.flags.bits.automatic && packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate)
13044+
{
13045+
// The GPS is automatically reporting, we just check whether we got unread data
13046+
checkUbloxInternal(&packetCfg, 0, 0); // Call checkUbloxInternal to parse any incoming data. Don't overwrite the requested Class and ID
13047+
return packetUBXNAVSIG->moduleQueried;
13048+
}
13049+
else if (packetUBXNAVSIG->automaticFlags.flags.bits.automatic && !packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate)
13050+
{
13051+
// Someone else has to call checkUblox for us...
13052+
return (false);
13053+
}
13054+
else
13055+
{
13056+
// The GPS is not automatically reporting NAVSIG so we have to poll explicitly
13057+
packetCfg.cls = UBX_CLASS_NAV;
13058+
packetCfg.id = UBX_NAV_SIG;
13059+
packetCfg.len = 0;
13060+
packetCfg.startingSpot = 0;
13061+
13062+
// The data is parsed as part of processing the response
13063+
sfe_ublox_status_e retVal = sendCommand(&packetCfg, maxWait);
13064+
13065+
if (retVal == SFE_UBLOX_STATUS_DATA_RECEIVED)
13066+
return (true);
13067+
13068+
if (retVal == SFE_UBLOX_STATUS_DATA_OVERWRITTEN)
13069+
{
13070+
return (true);
13071+
}
13072+
13073+
return (false);
13074+
}
13075+
}
13076+
13077+
// Enable or disable automatic NAVSIG message generation by the GNSS. This changes the way getNAVSIG
13078+
// works.
13079+
bool DevUBLOXGNSS::setAutoNAVSIG(bool enable, uint8_t layer, uint16_t maxWait)
13080+
{
13081+
return setAutoNAVSIGrate(enable ? 1 : 0, true, layer, maxWait);
13082+
}
13083+
13084+
// Enable or disable automatic NAVSIG message generation by the GNSS. This changes the way getNAVSIG
13085+
// works.
13086+
bool DevUBLOXGNSS::setAutoNAVSIG(bool enable, bool implicitUpdate, uint8_t layer, uint16_t maxWait)
13087+
{
13088+
return setAutoNAVSIGrate(enable ? 1 : 0, implicitUpdate, layer, maxWait);
13089+
}
13090+
13091+
// Enable or disable automatic NAV SAT message generation by the GNSS. This changes the way getNAVSIG
13092+
// works.
13093+
bool DevUBLOXGNSS::setAutoNAVSIGrate(uint8_t rate, bool implicitUpdate, uint8_t layer, uint16_t maxWait)
13094+
{
13095+
if (packetUBXNAVSIG == nullptr)
13096+
initPacketUBXNAVSIG(); // Check that RAM has been allocated for the data
13097+
if (packetUBXNAVSIG == nullptr) // Only attempt this if RAM allocation was successful
13098+
return false;
13099+
13100+
if (rate > 127)
13101+
rate = 127;
13102+
13103+
uint32_t key = UBLOX_CFG_MSGOUT_UBX_NAV_SIG_I2C;
13104+
if (_commType == COMM_TYPE_SPI)
13105+
key = UBLOX_CFG_MSGOUT_UBX_NAV_SIG_SPI;
13106+
else if (_commType == COMM_TYPE_SERIAL)
13107+
{
13108+
if (!_UART2)
13109+
key = UBLOX_CFG_MSGOUT_UBX_NAV_SIG_UART1;
13110+
else
13111+
key = UBLOX_CFG_MSGOUT_UBX_NAV_SIG_UART2;
13112+
}
13113+
13114+
bool ok = setVal8(key, rate, layer, maxWait);
13115+
if (ok)
13116+
{
13117+
packetUBXNAVSIG->automaticFlags.flags.bits.automatic = (rate > 0);
13118+
packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate = implicitUpdate;
13119+
}
13120+
packetUBXNAVSIG->moduleQueried = false; // Mark data as stale
13121+
return ok;
13122+
}
13123+
13124+
// Enable automatic navigation message generation by the GNSS.
13125+
bool DevUBLOXGNSS::setAutoNAVSIGcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_SIG_data_t *), uint8_t layer, uint16_t maxWait)
13126+
{
13127+
// Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually.
13128+
bool result = setAutoNAVSIG(true, false, layer, maxWait);
13129+
if (!result)
13130+
return (result); // Bail if setAuto failed
13131+
13132+
if (packetUBXNAVSIG->callbackData == nullptr) // Check if RAM has been allocated for the callback copy
13133+
{
13134+
packetUBXNAVSIG->callbackData = new UBX_NAV_SIG_data_t; // Allocate RAM for the main struct
13135+
}
13136+
13137+
if (packetUBXNAVSIG->callbackData == nullptr)
13138+
{
13139+
#ifndef SFE_UBLOX_REDUCED_PROG_MEM
13140+
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
13141+
_debugSerial.println(F("setAutoNAVSIGcallbackPtr: RAM alloc failed!"));
13142+
#endif
13143+
return (false);
13144+
}
13145+
13146+
packetUBXNAVSIG->callbackPointerPtr = callbackPointerPtr;
13147+
return (true);
13148+
}
13149+
13150+
// In case no config access to the GNSS is possible and NAV SAT is send cyclically already
13151+
// set config to suitable parameters
13152+
bool DevUBLOXGNSS::assumeAutoNAVSIG(bool enabled, bool implicitUpdate)
13153+
{
13154+
if (packetUBXNAVSIG == nullptr)
13155+
initPacketUBXNAVSIG(); // Check that RAM has been allocated for the NAVSIG data
13156+
if (packetUBXNAVSIG == nullptr) // Bail if the RAM allocation failed
13157+
return (false);
13158+
13159+
bool changes = packetUBXNAVSIG->automaticFlags.flags.bits.automatic != enabled || packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate != implicitUpdate;
13160+
if (changes)
13161+
{
13162+
packetUBXNAVSIG->automaticFlags.flags.bits.automatic = enabled;
13163+
packetUBXNAVSIG->automaticFlags.flags.bits.implicitUpdate = implicitUpdate;
13164+
}
13165+
return changes;
13166+
}
13167+
13168+
// PRIVATE: Allocate RAM for packetUBXNAVSIG and initialize it
13169+
bool DevUBLOXGNSS::initPacketUBXNAVSIG()
13170+
{
13171+
packetUBXNAVSIG = new UBX_NAV_SIG_t; // Allocate RAM for the main struct
13172+
if (packetUBXNAVSIG == nullptr)
13173+
{
13174+
#ifndef SFE_UBLOX_REDUCED_PROG_MEM
13175+
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
13176+
_debugSerial.println(F("initPacketUBXNAVSIG: RAM alloc failed!"));
13177+
#endif
13178+
return (false);
13179+
}
13180+
packetUBXNAVSIG->automaticFlags.flags.all = 0;
13181+
packetUBXNAVSIG->callbackPointerPtr = nullptr;
13182+
packetUBXNAVSIG->callbackData = nullptr;
13183+
packetUBXNAVSIG->moduleQueried = false;
13184+
return (true);
13185+
}
13186+
13187+
// Mark all the data as read/stale
13188+
void DevUBLOXGNSS::flushNAVSIG()
13189+
{
13190+
if (packetUBXNAVSIG == nullptr)
13191+
return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
13192+
packetUBXNAVSIG->moduleQueried = false; // Mark all datums as stale (read before)
13193+
}
13194+
13195+
// Log this data in file buffer
13196+
void DevUBLOXGNSS::logNAVSIG(bool enabled)
13197+
{
13198+
if (packetUBXNAVSIG == nullptr)
13199+
return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
13200+
packetUBXNAVSIG->automaticFlags.flags.bits.addToFileBuffer = (uint8_t)enabled;
13201+
}
1296113202
#endif
1296213203

1296313204
// ***** NAV RELPOSNED automatic support

0 commit comments

Comments
 (0)