diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml index 9e51dd2..4ef0d9a 100644 --- a/.github/workflows/compile-sketch.yml +++ b/.github/workflows/compile-sketch.yml @@ -86,7 +86,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Branch name run: echo running on branch ${GITHUB_REF##*/} diff --git a/examples/NEO-D9S_and_NEO-D9C/Example2_LBand_Corrections_with_NEO-D9S/Example2_LBand_Corrections_with_NEO-D9S.ino b/examples/NEO-D9S_and_NEO-D9C/Example2_LBand_Corrections_with_NEO-D9S/Example2_LBand_Corrections_with_NEO-D9S.ino index ae1e682..fa346d2 100644 --- a/examples/NEO-D9S_and_NEO-D9C/Example2_LBand_Corrections_with_NEO-D9S/Example2_LBand_Corrections_with_NEO-D9S.ino +++ b/examples/NEO-D9S_and_NEO-D9C/Example2_LBand_Corrections_with_NEO-D9S/Example2_LBand_Corrections_with_NEO-D9S.ino @@ -108,7 +108,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/examples/NEO-D9S_and_NEO-D9C/Example3_LBand_Corrections_with_NEO-D9S_using_SPI/Example3_LBand_Corrections_with_NEO-D9S_using_SPI.ino b/examples/NEO-D9S_and_NEO-D9C/Example3_LBand_Corrections_with_NEO-D9S_using_SPI/Example3_LBand_Corrections_with_NEO-D9S_using_SPI.ino index a0fb461..b369cbe 100644 --- a/examples/NEO-D9S_and_NEO-D9C/Example3_LBand_Corrections_with_NEO-D9S_using_SPI/Example3_LBand_Corrections_with_NEO-D9S_using_SPI.ino +++ b/examples/NEO-D9S_and_NEO-D9C/Example3_LBand_Corrections_with_NEO-D9S_using_SPI/Example3_LBand_Corrections_with_NEO-D9S_using_SPI.ino @@ -100,7 +100,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/examples/NEO-D9S_and_NEO-D9C/Example5_QZSSL6_Corrections_with_NEO-D9C/Example5_QZSSL6_Corrections_with_NEO-D9C.ino b/examples/NEO-D9S_and_NEO-D9C/Example5_QZSSL6_Corrections_with_NEO-D9C/Example5_QZSSL6_Corrections_with_NEO-D9C.ino index 9fc9ae0..7cb9ff3 100644 --- a/examples/NEO-D9S_and_NEO-D9C/Example5_QZSSL6_Corrections_with_NEO-D9C/Example5_QZSSL6_Corrections_with_NEO-D9C.ino +++ b/examples/NEO-D9S_and_NEO-D9C/Example5_QZSSL6_Corrections_with_NEO-D9C/Example5_QZSSL6_Corrections_with_NEO-D9C.ino @@ -126,7 +126,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/examples/NEO-D9S_and_NEO-D9C/Example6_PMP_with_L-Band_Keys_via_MQTT/Example6_PMP_with_L-Band_Keys_via_MQTT.ino b/examples/NEO-D9S_and_NEO-D9C/Example6_PMP_with_L-Band_Keys_via_MQTT/Example6_PMP_with_L-Band_Keys_via_MQTT.ino index 9184f19..0021f4c 100644 --- a/examples/NEO-D9S_and_NEO-D9C/Example6_PMP_with_L-Band_Keys_via_MQTT/Example6_PMP_with_L-Band_Keys_via_MQTT.ino +++ b/examples/NEO-D9S_and_NEO-D9C/Example6_PMP_with_L-Band_Keys_via_MQTT/Example6_PMP_with_L-Band_Keys_via_MQTT.ino @@ -132,7 +132,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/examples/NEO-D9S_and_NEO-D9C/Example7_LBand_Corrections_over_Serial/Example7_LBand_Corrections_over_Serial.ino b/examples/NEO-D9S_and_NEO-D9C/Example7_LBand_Corrections_over_Serial/Example7_LBand_Corrections_over_Serial.ino index 1f0724f..e1b54ad 100644 --- a/examples/NEO-D9S_and_NEO-D9C/Example7_LBand_Corrections_over_Serial/Example7_LBand_Corrections_over_Serial.ino +++ b/examples/NEO-D9S_and_NEO-D9C/Example7_LBand_Corrections_over_Serial/Example7_LBand_Corrections_over_Serial.ino @@ -97,7 +97,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/examples/NEO-D9S_and_NEO-D9C/Example8_LBand_SPARTN_Parsing/Example8_LBand_SPARTN_Parsing.ino b/examples/NEO-D9S_and_NEO-D9C/Example8_LBand_SPARTN_Parsing/Example8_LBand_SPARTN_Parsing.ino index f648391..17ef9d3 100644 --- a/examples/NEO-D9S_and_NEO-D9C/Example8_LBand_SPARTN_Parsing/Example8_LBand_SPARTN_Parsing.ino +++ b/examples/NEO-D9S_and_NEO-D9C/Example8_LBand_SPARTN_Parsing/Example8_LBand_SPARTN_Parsing.ino @@ -126,7 +126,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/examples/NEO-F10N/Example1_RAWX/Example1_RAWX.ino b/examples/NEO-F10N/Example1_RAWX/Example1_RAWX.ino index 030ccc1..aab7381 100644 --- a/examples/NEO-F10N/Example1_RAWX/Example1_RAWX.ino +++ b/examples/NEO-F10N/Example1_RAWX/Example1_RAWX.ino @@ -1,5 +1,5 @@ /* - Configuring the NEO-F10N GNSS to send RXM RAWX reports over I2C and display them using a callback + Configuring the NEO-F10N GNSS to send RXM RAWX reports over Serial and display them using a callback By: Paul Clark SparkFun Electronics Date: November 24th, 2023 @@ -8,20 +8,29 @@ This example shows how to configure the u-blox NEO-F10N GNSS to send RXM RAWX reports automatically and access the data via a callback. It also demonstrates how to mark the L5 signals as healthy. + Note: the NEO-F10N only supports UART1. It does not support I2C, SPI or built-in USB. + To run this example on the SparkFun NEO-F10N breakout, you need to open the USB-TX and USB-RX jumpers + to isolate the on-board CH340 USB interface chip. See Hardware Connections below. + + Note: the engineering sample of the NEO-F10N-00B supports RXM-RAWX. Production firmware may not. + Feel like supporting open source hardware? Buy a board from SparkFun! NEO-F10N: https://www.sparkfun.com/products/24114 Hardware Connections: - Plug a Qwiic cable into the GPS and a BlackBoard - If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425) + Open the USB-TX and USB-RX jumpers to isolate the on-board CH340 USB interface chip. + Solder header pins (9-way) to the board so you can access the UART1 TX and RX connections. + Use jumper wires to connect: + * TX to Serial1 RX on your Arduino board. + * RX to Serial1 TX on your Arduino board. + * GND to GND + * 5V to 5V (or 3V3 to 3V3) Open the serial monitor at 115200 baud to see the output */ -#include //Needed for I2C to GPS - #include //http://librarymanager/All#SparkFun_u-blox_GNSS_v3 -SFE_UBLOX_GNSS myGNSS; +SFE_UBLOX_GNSS_SERIAL myGNSS; // Callback: newRAWX will be called when new RXM RAWX data arrives // See u-blox_structs.h for the full definition of UBX_RXMRAWX_data_t @@ -209,9 +218,9 @@ void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct) else if (ubxDataStruct->blocks[block].svId < 100) sprintf(&SV[14], "%d ", ubxDataStruct->blocks[block].svId); // Align the svId else sprintf(&SV[14], "%d ", ubxDataStruct->blocks[block].svId); // Align the svId - if (ubxDataStruct->blocks[block].cno < 10) sprintf(&SV[18], " %d ", ubxDataStruct->blocks[block].cno); // Align the svId - else if (ubxDataStruct->blocks[block].cno < 100) sprintf(&SV[18], " %d ", ubxDataStruct->blocks[block].cno); // Align the svId - else sprintf(&SV[18], "%d ", ubxDataStruct->blocks[block].cno); // Align the svId + if (ubxDataStruct->blocks[block].cno < 10) sprintf(&SV[18], " %d ", ubxDataStruct->blocks[block].cno); // Align the cno + else if (ubxDataStruct->blocks[block].cno < 100) sprintf(&SV[18], " %d ", ubxDataStruct->blocks[block].cno); // Align the cno + else sprintf(&SV[18], "%d ", ubxDataStruct->blocks[block].cno); // Align the cno // Print cno as a bar chart uint8_t cno; @@ -231,25 +240,50 @@ void setup() while (!Serial); //Wait for user to open terminal Serial.println("SparkFun u-blox Example"); - Wire.begin(); + Serial1.begin(38400); // The NEO-F10N defaults to 38400 baud //myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port + while (myGNSS.begin(Serial1) == false) //Connect to the u-blox module using Serial1 (UART) { - Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing.")); - while (1); + Serial.println(F("u-blox GNSS not detected. Please check wiring. Retrying...")); + delay(1000); } - myGNSS.setGPSL5HealthOverride(true); // Mark L5 signals as healthy - store in RAM and BBR + if (myGNSS.getModuleInfo()) + { + Serial.print(F("FWVER: ")); + Serial.print(myGNSS.getFirmwareVersionHigh()); // Returns uint8_t + Serial.print(F(".")); + Serial.println(myGNSS.getFirmwareVersionLow()); // Returns uint8_t + + Serial.print(F("Firmware: ")); + Serial.println(myGNSS.getFirmwareType()); // Returns HPG, SPG, SPGL1L5 etc. as (const char *) - myGNSS.setLNAMode(SFE_UBLOX_LNA_MODE_NORMAL); // Set the LNA gain to normal (full). Other options: LOWGAIN, BYPASS + Serial.print(F("PROTVER: ")); + Serial.print(myGNSS.getProtocolVersionHigh()); // Returns uint8_t + Serial.print(F(".")); + Serial.println(myGNSS.getProtocolVersionLow()); // Returns uint8_t + + Serial.print(F("MOD: ")); + Serial.println(myGNSS.getModuleName()); // Returns ZED-F9P, MAX-M10S etc. as (const char *) + } + else + Serial.println(F("Error: could not read module info!")); - myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) + myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART1 port to output UBX only (turn off NMEA noise) myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR myGNSS.setMeasurementRate(5000); //Produce one solution every five seconds (RAWX produces a _lot_ of data!) + myGNSS.setVal8(UBLOX_CFG_SIGNAL_GPS_L5_ENA, 1); // Make sure the GPS L5 band is enabled (needed on the NEO-F9P) + + myGNSS.setGPSL5HealthOverride(true); // Mark L5 signals as healthy - store in RAM and BBR + + myGNSS.setLNAMode(SFE_UBLOX_LNA_MODE_NORMAL); // Set the LNA gain to normal (full). Other options: LOWGAIN, BYPASS + + myGNSS.softwareResetGNSSOnly(); // Restart the GNSS to apply the L5 health override + myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX } @@ -258,6 +292,15 @@ void loop() myGNSS.checkUblox(); // Check for the arrival of new data and process it. myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. - Serial.print("."); - delay(50); + printDot(); +} + +void printDot() // Print a dot every 200ms - without using delay +{ + static unsigned long lastPrint = millis(); + if (millis() > (lastPrint + 200)) + { + Serial.print("."); + lastPrint = millis(); + } } diff --git a/examples/NEO-F9P/Example1_RAWX/Example1_RAWX.ino b/examples/NEO-F9P/Example1_RAWX/Example1_RAWX.ino new file mode 100644 index 0000000..8c326e7 --- /dev/null +++ b/examples/NEO-F9P/Example1_RAWX/Example1_RAWX.ino @@ -0,0 +1,265 @@ +/* + Configuring the NEO-F9P GNSS to send RXM RAWX reports over I2C and display them using a callback + By: Paul Clark + SparkFun Electronics + Date: November 24th, 2023 + License: MIT. See license file for more information. + + This example shows how to configure the u-blox NEO-F9P GNSS to send RXM RAWX reports automatically + and access the data via a callback. It also demonstrates how to mark the L5 signals as healthy. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + NEO-F9P: https://www.sparkfun.com/products/23288 + + Hardware Connections: + Plug a Qwiic cable into the GPS and a BlackBoard + If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425) + Open the serial monitor at 115200 baud to see the output +*/ + +#include //Needed for I2C to GPS + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS_v3 +SFE_UBLOX_GNSS myGNSS; + +// Callback: newRAWX will be called when new RXM RAWX data arrives +// See u-blox_structs.h for the full definition of UBX_RXMRAWX_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMRAWXcallback +// / _____ This _must_ be UBX_RXM_RAWX_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct) +{ + Serial.println(); + + Serial.print(F("New RAWX data received. It contains ")); + Serial.print(ubxDataStruct->header.numMeas); // Print numMeas (Number of measurements / blocks) + Serial.println(F(" data blocks:")); + + for (uint8_t block = 0; block < ubxDataStruct->header.numMeas; block++) // For each block + { + char SV[14 + 4 + 4 + 256 + 1]; // Allocate space for sigId plus svId plus cno plus bars plus NULL + switch (ubxDataStruct->blocks[block].gnssId) + { + case 0: + { + switch (ubxDataStruct->blocks[block].sigId) + { + case 0: + sprintf(SV, "GPS L1 C/A "); + break; + case 3: + sprintf(SV, "GPS L2 CL "); + break; + case 4: + sprintf(SV, "GPS L2 CM "); + break; + case 6: + sprintf(SV, "GPS L5 I "); + break; + case 7: + sprintf(SV, "GPS L5 Q "); + break; + default: + sprintf(SV, "GPS Unknown "); + break; + } + } + break; + case 1: + { + switch (ubxDataStruct->blocks[block].sigId) + { + case 0: + sprintf(SV, "SBAS L1 C/A "); + break; + default: + sprintf(SV, "SBAS Unknown "); + break; + } + } + break; + case 2: + { + switch (ubxDataStruct->blocks[block].sigId) + { + case 0: + sprintf(SV, "Galileo E1 C "); + break; + case 1: + sprintf(SV, "Galileo E1 B "); + break; + case 3: + sprintf(SV, "Galileo E5 aI "); + break; + case 4: + sprintf(SV, "Galileo E5 aQ "); + break; + case 5: + sprintf(SV, "Galileo E5 bI "); + break; + case 6: + sprintf(SV, "Galileo E5 bQ "); + break; + default: + sprintf(SV, "GAL Unknown "); + break; + } + } + break; + case 3: + { + switch (ubxDataStruct->blocks[block].sigId) + { + case 0: + sprintf(SV, "BeiDou B1I D1 "); + break; + case 1: + sprintf(SV, "BeiDou B1I D2 "); + break; + case 2: + sprintf(SV, "BeiDou B2I D1 "); + break; + case 3: + sprintf(SV, "BeiDou B2I D2 "); + break; + case 5: + sprintf(SV, "BeiDou B1 Cp "); + break; + case 6: + sprintf(SV, "BeiDou B2 Cd "); + break; + case 7: + sprintf(SV, "BeiDou B2 ap "); + break; + case 8: + sprintf(SV, "BeiDou B2 ad "); + break; + default: + sprintf(SV, "BDS Unknown "); + break; + } + } + break; + case 5: + { + switch (ubxDataStruct->blocks[block].sigId) + { + case 0: + sprintf(SV, "QZSS L1 C/A "); + break; + case 1: + sprintf(SV, "QZSS L1S "); + break; + case 4: + sprintf(SV, "QZSS L2 CM "); + break; + case 5: + sprintf(SV, "QZSS L2 CL "); + break; + case 8: + sprintf(SV, "QZSS L5 I "); + break; + case 9: + sprintf(SV, "QZSS L5 Q "); + break; + default: + sprintf(SV, "QZSS Unknown "); + break; + } + } + break; + case 6: + { + switch (ubxDataStruct->blocks[block].sigId) + { + case 0: + sprintf(SV, "GLONASS L1 OF "); + break; + case 2: + sprintf(SV, "GLONASS L2 OF "); + break; + default: + sprintf(SV, "GLO Unknown "); + break; + } + } + break; + case 7: + { + switch (ubxDataStruct->blocks[block].sigId) + { + case 0: + sprintf(SV, "NavIC L5 A "); + break; + default: + sprintf(SV, "NavIC Unknown "); + break; + } + } + break; + default: + sprintf(SV, "Unknown "); + break; + } + + if (ubxDataStruct->blocks[block].svId < 10) sprintf(&SV[14], "%d ", ubxDataStruct->blocks[block].svId); // Align the svId + else if (ubxDataStruct->blocks[block].svId < 100) sprintf(&SV[14], "%d ", ubxDataStruct->blocks[block].svId); // Align the svId + else sprintf(&SV[14], "%d ", ubxDataStruct->blocks[block].svId); // Align the svId + + if (ubxDataStruct->blocks[block].cno < 10) sprintf(&SV[18], " %d ", ubxDataStruct->blocks[block].cno); // Align the cno + else if (ubxDataStruct->blocks[block].cno < 100) sprintf(&SV[18], " %d ", ubxDataStruct->blocks[block].cno); // Align the cno + else sprintf(&SV[18], "%d ", ubxDataStruct->blocks[block].cno); // Align the cno + + // Print cno as a bar chart + uint8_t cno; + for (cno = 0; cno <= ubxDataStruct->blocks[block].cno; cno++) + SV[22 + cno] = '='; + SV[22 + cno] = 0; // NULL + + Serial.println(SV); + } +} + +void setup() +{ + delay(1000); + + Serial.begin(115200); + while (!Serial); //Wait for user to open terminal + Serial.println("SparkFun u-blox Example"); + + Wire.begin(); + + //myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port + { + Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + + myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) + myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR + + myGNSS.setMeasurementRate(5000); //Produce one solution every five seconds (RAWX produces a _lot_ of data!) + + myGNSS.setVal8(UBLOX_CFG_SIGNAL_GPS_L5_ENA, 1); // Make sure the GPS L5 band is enabled (needed on the NEO-F9P) + + myGNSS.setGPSL5HealthOverride(true); // Mark L5 signals as healthy - store in RAM and BBR + + myGNSS.softwareResetGNSSOnly(); // Restart the GNSS to apply the L5 health override + + myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX +} + +void loop() +{ + myGNSS.checkUblox(); // Check for the arrival of new data and process it. + myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. + + Serial.print("."); + delay(200); +} diff --git a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino index a4d5c3f..df0bb54 100644 --- a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino +++ b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback/Example17_NTRIPClient_With_GGA_Callback.ino @@ -115,7 +115,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback__Serial/Example17_NTRIPClient_With_GGA_Callback__Serial.ino b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback__Serial/Example17_NTRIPClient_With_GGA_Callback__Serial.ino index e686a48..a0eab5a 100644 --- a/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback__Serial/Example17_NTRIPClient_With_GGA_Callback__Serial.ino +++ b/examples/ZED-F9P/Example17_NTRIPClient_With_GGA_Callback__Serial/Example17_NTRIPClient_With_GGA_Callback__Serial.ino @@ -120,7 +120,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino index e490b1c..cb37250 100644 --- a/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino +++ b/examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino @@ -87,7 +87,7 @@ void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct) Serial.print(F(" (2D)")); else if (fixType == 3) Serial.print(F(" (3D)")); - else if (fixType == 3) + else if (fixType == 4) Serial.print(F(" (GNSS + Dead Reckoning)")); else if (fixType == 5) Serial.print(F(" (Time Only)")); diff --git a/library.properties b/library.properties index c643e9a..dfab2c6 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS v3 -version=3.1.0 +version=3.1.1 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules

diff --git a/src/u-blox_GNSS.cpp b/src/u-blox_GNSS.cpp index f366900..f5c12b3 100644 --- a/src/u-blox_GNSS.cpp +++ b/src/u-blox_GNSS.cpp @@ -8140,7 +8140,7 @@ bool DevUBLOXGNSS::getModuleInfo(uint16_t maxWait) { ptr += strlen("FWVER="); // Point to the firmware type (HPG etc.) int i = 0; - while ((i < firmwareTypeLen) && (*ptr != '\0') && (*ptr != ' ')) // Extract the firmware type (3 chars) + while ((i < firmwareTypeLen) && (*ptr != '\0') && (*ptr != ' ')) // Extract the firmware type (3-7 chars) moduleSWVersion->firmwareType[i++] = *ptr++; moduleSWVersion->firmwareType[i] = '\0'; // NULL-terminate @@ -9106,7 +9106,7 @@ uint32_t DevUBLOXGNSS::uSpartnCrc32(const uint8_t *pU8Msg, size_t size) } // Parse SPARTN data -uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len) +uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len, sfe_ublox_spartn_header_t *header) { typedef enum { waitingFor73, @@ -9121,17 +9121,9 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len static uint8_t spartn[1100]; + static sfe_ublox_spartn_header_t _header; static uint16_t frameCount; - static uint8_t messageType; - static uint16_t payloadLength; - static uint16_t EAF; - static uint8_t crcType; static uint16_t crcBytes; - static uint8_t frameCRC; - static uint8_t messageSubtype; - static uint16_t timeTagType; - static uint16_t authenticationIndicator; - static uint16_t embeddedApplicationLengthBytes; static uint16_t TF007toTF016; valid = false; @@ -9150,21 +9142,21 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len spartn[1 + frameCount] = incoming; if (frameCount == 0) { - messageType = incoming >> 1; - payloadLength = incoming & 0x01; + _header.messageType = incoming >> 1; + _header.payloadLength = incoming & 0x01; } if (frameCount == 1) { - payloadLength <<= 8; - payloadLength |= incoming; + _header.payloadLength <<= 8; + _header.payloadLength |= incoming; } if (frameCount == 2) { - payloadLength <<= 1; - payloadLength |= incoming >> 7; - EAF = (incoming >> 6) & 0x01; - crcType = (incoming >> 4) & 0x03; - switch (crcType) + _header.payloadLength <<= 1; + _header.payloadLength |= incoming >> 7; + _header.EAF = (incoming >> 6) & 0x01; + _header.crcType = (incoming >> 4) & 0x03; + switch (_header.crcType) { case 0: crcBytes = 1; @@ -9179,9 +9171,9 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len crcBytes = 4; break; } - frameCRC = incoming & 0x0F; + _header.frameCRC = incoming & 0x0F; spartn[3] = spartn[3] & 0xF0; // Zero the 4 LSBs before calculating the CRC - if (uSpartnCrc4(&spartn[1], 3) == frameCRC) + if (uSpartnCrc4(&spartn[1], 3) == _header.frameCRC) { spartn[3] = incoming; // Restore TF005 and TF006 now we know the data is valid parseState = TF007; @@ -9189,11 +9181,11 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len if (_printDebug == true) { _debugSerial.print(F("SPARTN Header CRC is valid: payloadLength ")); - _debugSerial.print(payloadLength); + _debugSerial.print(_header.payloadLength); _debugSerial.print(F(" EAF ")); - _debugSerial.print(EAF); + _debugSerial.print(_header.EAF); _debugSerial.print(F(" crcType ")); - _debugSerial.println(crcType); + _debugSerial.println(_header.crcType); } #endif } @@ -9212,20 +9204,20 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len break; case TF007: spartn[4] = incoming; - messageSubtype = incoming >> 4; - timeTagType = (incoming >> 3) & 0x01; + _header.messageSubtype = incoming >> 4; + _header.timeTagType = (incoming >> 3) & 0x01; #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) { _debugSerial.print(F("SPARTN timeTagType ")); - _debugSerial.println(timeTagType); + _debugSerial.println(_header.timeTagType); } #endif - if (timeTagType == 0) + if (_header.timeTagType == 0) TF007toTF016 = 4; else TF007toTF016 = 6; - if (EAF > 0) + if (_header.EAF > 0) TF007toTF016 += 2; parseState = TF009; frameCount = 1; @@ -9235,41 +9227,41 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len frameCount++; if (frameCount == TF007toTF016) { - if (EAF == 0) + if (_header.EAF == 0) { - authenticationIndicator = 0; - embeddedApplicationLengthBytes = 0; + _header.authenticationIndicator = 0; + _header.embeddedApplicationLengthBytes = 0; } else { - authenticationIndicator = (incoming >> 3) & 0x07; + _header.authenticationIndicator = (incoming >> 3) & 0x07; #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) { _debugSerial.print(F("SPARTN authenticationIndicator ")); - _debugSerial.println(authenticationIndicator); + _debugSerial.println(_header.authenticationIndicator); } #endif - if (authenticationIndicator <= 1) - embeddedApplicationLengthBytes = 0; + if (_header.authenticationIndicator <= 1) + _header.embeddedApplicationLengthBytes = 0; else { switch(incoming & 0x07) { case 0: - embeddedApplicationLengthBytes = 8; // 64 bits + _header.embeddedApplicationLengthBytes = 8; // 64 bits break; case 1: - embeddedApplicationLengthBytes = 12; // 96 bits + _header.embeddedApplicationLengthBytes = 12; // 96 bits break; case 2: - embeddedApplicationLengthBytes = 16; // 128 bits + _header.embeddedApplicationLengthBytes = 16; // 128 bits break; case 3: - embeddedApplicationLengthBytes = 32; // 256 bits + _header.embeddedApplicationLengthBytes = 32; // 256 bits break; default: - embeddedApplicationLengthBytes = 64; // 512 / TBD bits + _header.embeddedApplicationLengthBytes = 64; // 512 / TBD bits break; } } @@ -9277,7 +9269,7 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len if (_printDebug == true) { _debugSerial.print(F("SPARTN embeddedApplicationLengthBytes ")); - _debugSerial.println(embeddedApplicationLengthBytes); + _debugSerial.println(_header.embeddedApplicationLengthBytes); } #endif } @@ -9288,9 +9280,9 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len case TF016: spartn[4 + TF007toTF016 + frameCount] = incoming; frameCount++; - if (frameCount == payloadLength) + if (frameCount == _header.payloadLength) { - if (embeddedApplicationLengthBytes > 0) + if (_header.embeddedApplicationLengthBytes > 0) { parseState = TF017; frameCount = 0; @@ -9303,21 +9295,21 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len } break; case TF017: - spartn[4 + TF007toTF016 + payloadLength + frameCount] = incoming; + spartn[4 + TF007toTF016 + _header.payloadLength + frameCount] = incoming; frameCount++; - if (frameCount == embeddedApplicationLengthBytes) + if (frameCount == _header.embeddedApplicationLengthBytes) { parseState = TF018; frameCount = 0; } break; case TF018: - spartn[4 + TF007toTF016 + payloadLength + embeddedApplicationLengthBytes + frameCount] = incoming; + spartn[4 + TF007toTF016 + _header.payloadLength + _header.embeddedApplicationLengthBytes + frameCount] = incoming; frameCount++; if (frameCount == crcBytes) { parseState = waitingFor73; - uint16_t numBytes = 4 + TF007toTF016 + payloadLength + embeddedApplicationLengthBytes; + uint16_t numBytes = 4 + TF007toTF016 + _header.payloadLength + _header.embeddedApplicationLengthBytes; #ifndef SFE_UBLOX_REDUCED_PROG_MEM if (_printDebug == true) { @@ -9326,7 +9318,7 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len } #endif uint8_t *ptr = &spartn[numBytes]; - switch (crcType) + switch (_header.crcType) { case 0: { @@ -9398,8 +9390,8 @@ uint8_t * DevUBLOXGNSS::parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len break; } - (void)messageType; // Avoid pesky compiler warnings-as-errors - (void)messageSubtype; + if (header != nullptr) + memcpy(header, &_header, sizeof(sfe_ublox_spartn_header_t)); return &spartn[0]; } diff --git a/src/u-blox_GNSS.h b/src/u-blox_GNSS.h index 101b4c6..1e5e3a4 100644 --- a/src/u-blox_GNSS.h +++ b/src/u-blox_GNSS.h @@ -470,7 +470,7 @@ class DevUBLOXGNSS uint16_t uSpartnCrc16(const uint8_t *pU8Msg, size_t size); uint32_t uSpartnCrc24(const uint8_t *pU8Msg, size_t size); uint32_t uSpartnCrc32(const uint8_t *pU8Msg, size_t size); - uint8_t * parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len); + uint8_t * parseSPARTN(uint8_t incoming, bool &valid, uint16_t &len, sfe_ublox_spartn_header_t *header = nullptr); // Get unique chip ID - UBX-SEC-UNIQID bool getUniqueChipId(UBX_SEC_UNIQID_data_t *data = nullptr, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Get the unique chip ID using UBX_SEC_UNIQID diff --git a/src/u-blox_external_typedefs.h b/src/u-blox_external_typedefs.h index c0bbe34..773f142 100644 --- a/src/u-blox_external_typedefs.h +++ b/src/u-blox_external_typedefs.h @@ -253,7 +253,7 @@ struct sfe_ublox_ubx_logging_list_t #ifndef MAX_PAYLOAD_SIZE // v2.0: keep this for backwards-compatibility, but this is largely superseded by setPacketCfgPayloadSize -#define MAX_PAYLOAD_SIZE 246 // We need ~220 bytes for getProtocolVersion on most ublox modules +#define MAX_PAYLOAD_SIZE 276 // We need >=250 bytes for getProtocolVersion on the NEO-F10N // #define MAX_PAYLOAD_SIZE 768 //Worst case: UBX_CFG_VALSET packet with 64 keyIDs each with 64 bit values #endif @@ -303,7 +303,7 @@ typedef struct } geofenceParams_t; // Struct to hold the module software version -#define firmwareTypeLen 3 // HPG, SPG, etc. +#define firmwareTypeLen 7 // HPG, SPG, SPGL1L5, etc. #define moduleNameMaxLen 13 // Allow for: 4-chars minus 4-chars minus 3-chars typedef struct { @@ -342,6 +342,19 @@ const uint32_t SFE_UBLOX_SECS_PER_WEEK = 60 * 60 * 24 * 7; // Seconds per week // SPARTN CRC calculation // Stolen from https://github.com/u-blox/ubxlib/blob/master/common/spartn/src/u_spartn_crc.c +typedef struct +{ + uint8_t messageType; + uint16_t payloadLength; + uint16_t EAF; + uint8_t crcType; + uint8_t frameCRC; + uint8_t messageSubtype; + uint16_t timeTagType; + uint16_t authenticationIndicator; + uint16_t embeddedApplicationLengthBytes; +} sfe_ublox_spartn_header_t; + const uint8_t sfe_ublox_u8Crc4Table[] = { 0x00U, 0x0BU, 0x05U, 0x0EU, 0x0AU, 0x01U, 0x0FU, 0x04U, 0x07U, 0x0CU, 0x02U, 0x09U, 0x0DU, 0x06U, 0x08U, 0x03U,