Skip to content

Commit ab058f0

Browse files
authored
Merge pull request #145 from mazgch/mazgch-support-NEOD9C
Add basic support NEO-D9C
2 parents a5b1da4 + 1e5c02c commit ab058f0

4 files changed

+183
-0
lines changed

src/SparkFun_u-blox_GNSS_Arduino_Library.cpp

+102
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,16 @@ void SFE_UBLOX_GNSS::end(void)
341341
packetUBXRXMPMPmessage = NULL; // Redundant?
342342
}
343343

344+
if (packetUBXRXMQZSSL6message != NULL)
345+
{
346+
if (packetUBXRXMQZSSL6message->callbackData != NULL)
347+
{
348+
delete [] packetUBXRXMQZSSL6message->callbackData;
349+
}
350+
delete packetUBXRXMQZSSL6message;
351+
packetUBXRXMQZSSL6message = NULL; // Redundant?
352+
}
353+
344354
if (packetUBXRXMCOR != NULL)
345355
{
346356
if (packetUBXRXMCOR->callbackData != NULL)
@@ -1398,6 +1408,10 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID)
13981408
if ((packetUBXRXMPMP != NULL) || (packetUBXRXMPMPmessage != NULL))
13991409
result = true;
14001410
break;
1411+
case UBX_RXM_QZSSL6:
1412+
if (packetUBXRXMQZSSL6message != NULL)
1413+
result = true;
1414+
break;
14011415
case UBX_RXM_COR:
14021416
if (packetUBXRXMCOR != NULL)
14031417
result = true;
@@ -1579,6 +1593,9 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID)
15791593
case UBX_RXM_PMP:
15801594
maxSize = UBX_RXM_PMP_MAX_LEN;
15811595
break;
1596+
case UBX_RXM_QZSSL6:
1597+
maxSize = UBX_RXM_QZSSL6_MAX_LEN;
1598+
break;
15821599
case UBX_RXM_COR:
15831600
maxSize = UBX_RXM_COR_LEN;
15841601
break;
@@ -3923,6 +3940,31 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg)
39233940
packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = true; // Mark the data as valid
39243941
}
39253942
}
3943+
if (msg->id == UBX_RXM_QZSSL6)
3944+
// Note: length is variable with version 0x01
3945+
// Note: the field positions depend on the version
3946+
{
3947+
// Full QZSSL6 message, including Class, ID and checksum
3948+
for (int ch = 0; ch < UBX_RXM_QZSSL6_NUM_CHANNELS; ch ++) {
3949+
if (0 == (packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid & (1 << ch))) {
3950+
3951+
packetUBXRXMQZSSL6message->callbackData[ch].sync1 = UBX_SYNCH_1;
3952+
packetUBXRXMQZSSL6message->callbackData[ch].sync2 = UBX_SYNCH_2;
3953+
packetUBXRXMQZSSL6message->callbackData[ch].cls = UBX_CLASS_RXM;
3954+
packetUBXRXMQZSSL6message->callbackData[ch].ID = UBX_RXM_QZSSL6;
3955+
packetUBXRXMQZSSL6message->callbackData[ch].lengthLSB = msg->len & 0xFF;
3956+
packetUBXRXMQZSSL6message->callbackData[ch].lengthMSB = msg->len >> 8;
3957+
3958+
memcpy(packetUBXRXMQZSSL6message->callbackData[ch].payload, msg->payload, msg->len);
3959+
3960+
packetUBXRXMQZSSL6message->callbackData[ch].checksumA = msg->checksumA;
3961+
packetUBXRXMQZSSL6message->callbackData[ch].checksumB = msg->checksumB;
3962+
3963+
packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid |= (1 << ch);
3964+
break; // abort when added
3965+
}
3966+
}
3967+
}
39263968
else if (msg->id == UBX_RXM_COR)
39273969
{
39283970
// Parse various byte fields into storage - but only if we have memory allocated for it
@@ -5563,6 +5605,19 @@ void SFE_UBLOX_GNSS::checkCallbacks(void)
55635605
packetUBXRXMPMPmessage->callbackPointerPtr(packetUBXRXMPMPmessage->callbackData); // Call the callback
55645606
packetUBXRXMPMPmessage->automaticFlags.flags.bits.callbackCopyValid = false; // Mark the data as stale
55655607
}
5608+
5609+
if ((packetUBXRXMQZSSL6message != NULL) && // If RAM has been allocated for message storage
5610+
(packetUBXRXMQZSSL6message->callbackData != NULL) && // If RAM has been allocated for the copy of the data
5611+
(packetUBXRXMQZSSL6message->callbackPointerPtr != NULL)) // If the pointer to the callback has been defined
5612+
{
5613+
for (int ch = 0; ch < UBX_RXM_QZSSL6_NUM_CHANNELS; ch ++) {
5614+
if (packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid & (1 << ch)) // If the copy of the data is valid
5615+
{
5616+
packetUBXRXMQZSSL6message->callbackPointerPtr( &packetUBXRXMQZSSL6message->callbackData[ch] ); // Call the callback
5617+
packetUBXRXMQZSSL6message->automaticFlags.flags.bits.callbackCopyValid &= ~(1 << ch); // clear it
5618+
}
5619+
}
5620+
}
55665621

55675622
if ((packetUBXRXMCOR != NULL) // If RAM has been allocated for message storage
55685623
&& (packetUBXRXMCOR->callbackData != NULL) // If RAM has been allocated for the copy of the data
@@ -13029,6 +13084,53 @@ bool SFE_UBLOX_GNSS::initPacketUBXRXMPMPmessage()
1302913084
return (true);
1303013085
}
1303113086

13087+
// ***** RXM QZSSL6 automatic support
13088+
13089+
// Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack!
13090+
bool SFE_UBLOX_GNSS::setRXMQZSSL6messageCallbackPtr(void (*callbackPointer)(UBX_RXM_QZSSL6_message_data_t *))
13091+
{
13092+
if (packetUBXRXMQZSSL6message == NULL)
13093+
initPacketUBXRXMQZSSL6message(); // Check that RAM has been allocated for the data
13094+
if (packetUBXRXMQZSSL6message == NULL) // Only attempt this if RAM allocation was successful
13095+
return false;
13096+
13097+
if (packetUBXRXMQZSSL6message->callbackData == NULL) // Check if RAM has been allocated for the callback copy
13098+
{
13099+
packetUBXRXMQZSSL6message->callbackData = new UBX_RXM_QZSSL6_message_data_t[UBX_RXM_QZSSL6_NUM_CHANNELS]; // Allocate RAM for the main struct
13100+
}
13101+
13102+
if (packetUBXRXMQZSSL6message->callbackData == NULL)
13103+
{
13104+
#ifndef SFE_UBLOX_REDUCED_PROG_MEM
13105+
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
13106+
_debugSerial->println(F("setAutoRXMQZSSL6messagecallbackPtr: RAM alloc failed!"));
13107+
#endif
13108+
return (false);
13109+
}
13110+
13111+
packetUBXRXMQZSSL6message->callbackPointerPtr = callbackPointer;
13112+
return (true);
13113+
}
13114+
13115+
// PRIVATE: Allocate RAM for packetUBXRXMQZSSL6message and initialize it
13116+
bool SFE_UBLOX_GNSS::initPacketUBXRXMQZSSL6message()
13117+
{
13118+
packetUBXRXMQZSSL6message = new UBX_RXM_QZSSL6_message_t; // Allocate RAM for the main struct
13119+
if (packetUBXRXMQZSSL6message == NULL)
13120+
{
13121+
#ifndef SFE_UBLOX_REDUCED_PROG_MEM
13122+
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
13123+
_debugSerial->println(F("initPacketUBXRXMQZSSL6message: RAM alloc failed!"));
13124+
#endif
13125+
return (false);
13126+
}
13127+
packetUBXRXMQZSSL6message->automaticFlags.flags.all = 0;
13128+
packetUBXRXMQZSSL6message->callbackPointerPtr = NULL;
13129+
packetUBXRXMQZSSL6message->callbackData = NULL;
13130+
return (true);
13131+
}
13132+
13133+
1303213134
bool SFE_UBLOX_GNSS::setRXMCORcallbackPtr(void (*callbackPointer)(UBX_RXM_COR_data_t *))
1303313135
{
1303413136
if (packetUBXRXMCOR == NULL)

src/SparkFun_u-blox_GNSS_Arduino_Library.h

+9
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ const uint8_t UBX_NAV_AOPSTATUS = 0x60; // AssistNow Autonomous status
397397
const uint8_t UBX_RXM_COR = 0x34; // Differential correction input status
398398
const uint8_t UBX_RXM_MEASX = 0x14; // Satellite Measurements for RRLP
399399
const uint8_t UBX_RXM_PMP = 0x72; // PMP raw data (NEO-D9S) (two different versions) (packet size for version 0x01 is variable)
400+
const uint8_t UBX_RXM_QZSSL6 = 0x73; // QZSSL6 data (NEO-D9C)
400401
const uint8_t UBX_RXM_PMREQ = 0x41; // Requests a Power Management task (two different packet sizes)
401402
const uint8_t UBX_RXM_RAWX = 0x15; // Multi-GNSS Raw Measurement Data
402403
const uint8_t UBX_RXM_RLM = 0x59; // Galileo SAR Short-RLM report (two different packet sizes)
@@ -1181,6 +1182,12 @@ class SFE_UBLOX_GNSS
11811182
bool setRXMPMPcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_data_t *)); // Callback receives a pointer to the data, instead of _all_ the data. Much kinder on the stack!
11821183
bool setRXMPMPmessageCallbackPtr(void (*callbackPointerPtr)(UBX_RXM_PMP_message_data_t *)); // Use this if you want all of the PMP message (including sync chars, checksum, etc.) to push to a GNSS
11831184

1185+
// Configure a callback for the UBX-RXM-QZSSL6 messages produced by the NEO-D9C
1186+
// Note: on the NEO-D9C, the UBX-RXM-QZSSL6 messages are enabled by default on all ports.
1187+
// You can disable them by calling (e.g.) setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_I2C, 0)
1188+
// The NEO-D9C does not support UBX-CFG-MSG
1189+
bool setRXMQZSSL6messageCallbackPtr(void (*callbackPointerPtr)(UBX_RXM_QZSSL6_message_data_t *)); // Use this if you want all of the QZSSL6 message (including sync chars, checksum, etc.) to push to a GNSS
1190+
11841191
bool setRXMCORcallbackPtr(void (*callbackPointerPtr)(UBX_RXM_COR_data_t *)); // RXM COR
11851192

11861193
bool getRXMSFRBX(uint16_t maxWait = defaultMaxWait); // RXM SFRBX
@@ -1538,6 +1545,7 @@ class SFE_UBLOX_GNSS
15381545

15391546
UBX_RXM_PMP_t *packetUBXRXMPMP = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
15401547
UBX_RXM_PMP_message_t *packetUBXRXMPMPmessage = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
1548+
UBX_RXM_QZSSL6_message_t *packetUBXRXMQZSSL6message = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
15411549
UBX_RXM_COR_t *packetUBXRXMCOR = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
15421550
UBX_RXM_SFRBX_t *packetUBXRXMSFRBX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
15431551
UBX_RXM_RAWX_t *packetUBXRXMRAWX = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
@@ -1639,6 +1647,7 @@ class SFE_UBLOX_GNSS
16391647
bool initPacketUBXNAVEOE(); // Allocate RAM for packetUBXNAVEOE and initialize it
16401648
bool initPacketUBXRXMPMP(); // Allocate RAM for packetUBXRXMPMP and initialize it
16411649
bool initPacketUBXRXMPMPmessage(); // Allocate RAM for packetUBXRXMPMPRaw and initialize it
1650+
bool initPacketUBXRXMQZSSL6message(); // Allocate RAM for packetUBXRXMQZSSL6raw and initialize it
16421651
bool initPacketUBXRXMCOR(); // Allocate RAM for packetUBXRXMCOR and initialize it
16431652
bool initPacketUBXRXMSFRBX(); // Allocate RAM for packetUBXRXMSFRBX and initialize it
16441653
bool initPacketUBXRXMRAWX(); // Allocate RAM for packetUBXRXMRAWX and initialize it

src/u-blox_config_keys.h

+16
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,14 @@ const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_UART1 = 0x20910323; // Output rate o
826826
const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_UART2 = 0x20910324; // Output rate of the UBX_MON_PMP message on port UART2
827827
const uint32_t UBLOX_CFG_MSGOUT_UBX_MON_PMP_USB = 0x20910325; // Output rate of the UBX_MON_PMP message on port USB
828828

829+
// Additional CFG_MSGOUT keys for the NEO-D9S
830+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
831+
const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_I2C = 0x2091033f; // Output rate of the UBX_RXM_QZSSL6 message on port I2C
832+
const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_SPI = 0x2091033e; // Output rate of the UBX_RXM_QZSSL6 message on port SPI
833+
const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_UART1 = 0x2091033b; // Output rate of the UBX_RXM_QZSSL6 message on port UART1
834+
const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_UART2 = 0x2091033c; // Output rate of the UBX_RXM_QZSSL6 message on port UART2
835+
const uint32_t UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_USB = 0x2091033d; // Output rate of the UBX_RXM_QZSSL6 message on port USB
836+
829837
// CFG-NAV2: Secondary output configuration
830838
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
831839
const uint32_t UBLOX_CFG_NAV2_OUT_ENABLED = 0x10170001; // Enable secondary (NAV2) output
@@ -928,6 +936,14 @@ const uint32_t UBLOX_CFG_PMP_DESCRAMBLER_INIT = 0x30b10015; // Descrambler init
928936
const uint32_t UBLOX_CFG_PMP_USE_PRESCRAMBLING = 0x10b10019; // Use prescrambling. Enables/disables the prescrambling.
929937
const uint32_t UBLOX_CFG_PMP_UNIQUE_WORD = 0x50b1001a; // Unique word. Defines value of unique word.
930938

939+
// CFG-QZSS-L6: QZSS system configuration configuration (NEO-D9C)
940+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
941+
const uint32_t UBLOX_CFG_QZSSL6_SVIDA = 0x20370020; // QZSS L6 SV Id to be decoded by channel A
942+
const uint32_t UBLOX_CFG_QZSSL6_SVIDB = 0x20370030; // QZSS L6 SV Id to be decoded by channel B
943+
const uint32_t UBLOX_CFG_QZSSL6_MSGA = 0x20370050; // QZSS L6 messages to be decoded by channel A
944+
const uint32_t UBLOX_CFG_QZSSL6_MSGB = 0x20370060; // QZSS L6 messages to be decoded by channel B
945+
const uint32_t UBLOX_CFG_QZSSL6_RSDECODER = 0x20370080; // QZSS L6 message Reed-Solomon decoder mode
946+
931947
// CFG-QZSS: QZSS system configuration
932948
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
933949
const uint32_t UBLOX_CFG_QZSS_USE_SLAS_DGNSS = 0x10370005; // Apply QZSS SLAS DGNSS corrections

src/u-blox_structs.h

+56
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,62 @@ typedef struct
16291629
UBX_RXM_PMP_message_data_t *callbackData;
16301630
} UBX_RXM_PMP_message_t;
16311631

1632+
// UBX-RXM-QZSSL6 (0x02 0x73): QZSS L6 raw data (D9C modules)
1633+
#define UBX_RXM_QZSSL6_NUM_CHANNELS 2
1634+
const uint16_t UBX_RXM_QZSSL6_DATALEN = 250;
1635+
const uint16_t UBX_RXM_QZSSL6_MAX_LEN = UBX_RXM_QZSSL6_DATALEN + 14;
1636+
1637+
typedef struct
1638+
{
1639+
uint8_t version; // Message version (0x00 / 0x01)
1640+
uint8_t svId; // Satellite identifier
1641+
uint16_t cno; // Mean C/N0
1642+
uint32_t timeTag; // Time since startup when frame started : ms
1643+
uint8_t groupDelay; // L6 group delay w.r.t. L2 on channel
1644+
uint8_t bitErrCorr; // Number of bit errors corrected by Reed-Solomon decoder
1645+
uint16_t chInfo; // Information about receiver channel associated with a received QZSS L6 message
1646+
uint8_t reserved0[2]; // Reserved
1647+
uint8_t msgBytes[UBX_RXM_QZSSL6_DATALEN]; // Bytes in a QZSS L6 message
1648+
} UBX_RXM_QZSSL6_data_t;
1649+
1650+
struct ubxQZSSL6AutomaticFlags
1651+
{
1652+
union
1653+
{
1654+
uint8_t all;
1655+
struct
1656+
{
1657+
uint8_t automatic : 1; // Will this message be delivered and parsed "automatically" (without polling)
1658+
uint8_t implicitUpdate : 1; // Is the update triggered by accessing stale data (=true) or by a call to checkUblox (=false)
1659+
uint8_t addToFileBuffer : 1; // Should the raw UBX data be added to the file buffer?
1660+
uint8_t callbackCopyValid : UBX_RXM_QZSSL6_NUM_CHANNELS; // Is the copies of the data structs used by the callback valid/fresh?
1661+
} bits;
1662+
} flags;
1663+
};
1664+
1665+
// Define a struct to hold the entire QZSSL6 message so the whole thing can be pushed to a GNSS.
1666+
// Remember that the length of the payload could be variable (with version 1 messages).
1667+
typedef struct
1668+
{
1669+
uint8_t sync1; // 0xB5
1670+
uint8_t sync2; // 0x62
1671+
uint8_t cls;
1672+
uint8_t ID;
1673+
uint8_t lengthLSB;
1674+
uint8_t lengthMSB;
1675+
uint8_t payload[UBX_RXM_QZSSL6_MAX_LEN];
1676+
uint8_t checksumA;
1677+
uint8_t checksumB;
1678+
} UBX_RXM_QZSSL6_message_data_t;
1679+
1680+
// The QZSSL6 data can only be accessed via a callback. QZSSL6 cannot be polled.
1681+
typedef struct
1682+
{
1683+
ubxQZSSL6AutomaticFlags automaticFlags;
1684+
void (*callbackPointerPtr)(UBX_RXM_QZSSL6_message_data_t *);
1685+
UBX_RXM_QZSSL6_message_data_t *callbackData;
1686+
} UBX_RXM_QZSSL6_message_t;
1687+
16321688
// CFG-specific structs
16331689

16341690
// UBX-CFG-PRT (0x06 0x00): Port configuration

0 commit comments

Comments
 (0)