Skip to content

Commit e316a67

Browse files
authored
Merge pull request #7 from LeeLeahy2/ex-17
Example 17: Add a position, velocity and time example that uses SEMP
2 parents 679a8c7 + 208d388 commit e316a67

File tree

1 file changed

+389
-0
lines changed

1 file changed

+389
-0
lines changed
Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
/*
2+
This example configures the UM980 inside the Torch.
3+
4+
NMEA, some RTCM, and BESTNAV (binary) are enabled and output at 1Hz.
5+
*/
6+
7+
#include <SparkFun_Unicore_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_Unicore_GNSS
8+
#include <SparkFun_Extensible_Message_Parser.h> //http://librarymanager/All#SparkFun_Extensible_Message_Parser
9+
10+
//----------------------------------------
11+
// Constants
12+
//----------------------------------------
13+
14+
int pin_UART1_TX = 4;
15+
int pin_UART1_RX = 13;
16+
17+
#define COMPILE_CAPTURE_RAW_DATA_STREAM 0
18+
#define COMPILE_PARSER_STATE_DISPLAY 0
19+
#define CAPTURE_BYTE_COUNT 8192 // 0 means infinite
20+
21+
// Build the table listing all of the parsers
22+
SEMP_PARSE_ROUTINE const parserTable[] =
23+
{
24+
sempNmeaPreamble,
25+
sempNmeaHashPreamble,
26+
sempRtcmPreamble,
27+
sempUnicorePreamble,
28+
};
29+
const int parserCount = sizeof(parserTable) / sizeof(parserTable[0]);
30+
31+
const char * const parserNames[] =
32+
{
33+
"NMEA_$",
34+
"NMEA_#",
35+
"RTCM",
36+
"Unicore",
37+
};
38+
const int parserNameCount = sizeof(parserNames) / sizeof(parserNames[0]);
39+
40+
#define CONVERT_TO_C_BYTES_PER_LINE 8 // Must be a power of 2
41+
#define CONVERT_TO_C_BYTES_PER_MASK (CONVERT_TO_C_BYTES_PER_LINE - 1)
42+
43+
//----------------------------------------
44+
// Locals
45+
//----------------------------------------
46+
47+
UM980 myGNSS;
48+
49+
HardwareSerial SerialGNSS(1); //Use UART1 on the ESP32
50+
51+
unsigned long lastCheck = 0;
52+
53+
uint32_t dataOffset; // Offset in rawDataStream array
54+
int32_t offset; // invalidCharacterBuffer offset
55+
uint8_t invalidCharacterBuffer[20000]; // Data that was not parsed
56+
SEMP_PARSE_STATE *parse; // State of the parsers
57+
58+
//----------------------------------------
59+
// UM980 Initialization Example
60+
//----------------------------------------
61+
62+
void setup()
63+
{
64+
Serial.begin(115200);
65+
delay(250);
66+
Serial.println();
67+
Serial.println("SparkFun UM980 Example");
68+
69+
//We must start the serial port before using it in the library
70+
SerialGNSS.begin(115200, SERIAL_8N1, pin_UART1_RX, pin_UART1_TX);
71+
72+
myGNSS.enableDebugging(); // Print all debug to Serial
73+
74+
// Enable debugging
75+
if (myGNSS.begin(SerialGNSS) == false) //Give the serial port over to the library
76+
{
77+
Serial.println("UM980 failed to respond. Check ports and baud rates. Freezing...");
78+
while (true);
79+
}
80+
Serial.println("UM980 detected!");
81+
82+
// Clear saved configurations, satellite ephemerides, position information, and reset baud rate to 115200bps.
83+
resetUM980();
84+
85+
bool response = true;
86+
87+
float outputRate = 1; //0.5 = 2 reports per second.
88+
89+
char comPort[] = "COM3"; //UM980 UART3 is connected to ESP32 UART1 on the Torch
90+
91+
//Enable some RTCM, NMEA, and a UM980 binary command called BESTNAVB
92+
response &= myGNSS.setRTCMPortMessage("RTCM1005", comPort, outputRate);
93+
response &= myGNSS.setRTCMPortMessage("RTCM1074", comPort, outputRate);
94+
95+
response &= myGNSS.setNMEAPortMessage("GPGGA", comPort, outputRate);
96+
response &= myGNSS.setNMEAPortMessage("GPGSA", comPort, outputRate);
97+
response &= myGNSS.setNMEAPortMessage("GPGST", comPort, outputRate);
98+
response &= myGNSS.setNMEAPortMessage("GPGSV", comPort, outputRate);
99+
response &= myGNSS.setNMEAPortMessage("GPRMC", comPort, outputRate);
100+
response &= myGNSS.saveConfiguration(); //Save the current configuration into non-volatile memory (NVM)
101+
102+
//If any one command fails, it will force response to false
103+
if (response == false)
104+
{
105+
Serial.println("UM980 failed to configure. Freezing...");
106+
while (true);
107+
}
108+
109+
//sendCommand() sends the string directly and checks for the OK response
110+
//Returns true if the OK was detected
111+
//"BESTNAVB 1" starts the output of BESTNAV binary message at 1Hz on the COM port
112+
//we are connected to (in this case COM3)
113+
if (myGNSS.sendCommand("BESTNAVB 1") == true)
114+
Serial.println("BESTNAVB enabled");
115+
else
116+
Serial.println("BESTNAVB error");
117+
118+
// Initialize the parser
119+
parse = sempBeginParser(parserTable, parserCount,
120+
parserNames, parserNameCount,
121+
0, 3000, processMessage, "Example 17 Parser");
122+
if (!parse)
123+
reportFatalError("Failed to initialize the parser");
124+
125+
// Enable debugging for the parser
126+
sempEnableDebugOutput(parse);
127+
128+
if (COMPILE_CAPTURE_RAW_DATA_STREAM)
129+
{
130+
// Disable parser output
131+
sempDisableDebugOutput(parse);
132+
sempDisableErrorOutput(parse);
133+
Serial.println("const uint8_t rawDataStream[] =");
134+
Serial.println("{");
135+
}
136+
137+
Serial.println("Mixture of NMEA, RTCM, and UM980 binary now reporting. Have fun!");
138+
}
139+
140+
void loop()
141+
{
142+
const char * startState;
143+
const char * endState;
144+
145+
// Read the raw data one byte at a time and update the parser state
146+
// based on the incoming byte
147+
while (SerialGNSS.available())
148+
{
149+
// Read the byte from the UM980
150+
uint8_t incoming = SerialGNSS.read();
151+
152+
// Remember this data byte
153+
// Ignore CR and LF following NMEA checksum
154+
if ((parse->type != 0) || ((incoming != '\r') && (incoming != '\n')))
155+
invalidCharacterBuffer[offset++] = incoming;
156+
157+
// Parse this byte
158+
startState = getParseStateName(parse);
159+
sempParseNextByte(parse, incoming);
160+
endState = getParseStateName(parse);
161+
162+
// Build a rawDataStream array
163+
if (COMPILE_CAPTURE_RAW_DATA_STREAM)
164+
{
165+
if ((!CAPTURE_BYTE_COUNT)
166+
|| (dataOffset < CAPTURE_BYTE_COUNT))
167+
// Add the incoming data byte to the rawDataStream
168+
convertToC(incoming);
169+
else if (dataOffset == CAPTURE_BYTE_COUNT)
170+
{
171+
// Finish the rawDataStream array
172+
convertToCComment(true);
173+
dataOffset += 1;
174+
}
175+
}
176+
177+
// Display the state changes
178+
else if (COMPILE_PARSER_STATE_DISPLAY)
179+
Serial.printf("Ex17: 0x%02x (%c), state: (%p) %s --> %s (%p)\r\n",
180+
incoming,
181+
((incoming >= ' ') && (incoming < 0x7f)) ? incoming : '.',
182+
startState, startState, endState, endState);
183+
}
184+
}
185+
186+
void resetUM980()
187+
{
188+
if (myGNSS.factoryReset() == true)
189+
Serial.println("UM980 now reset to factory defaults");
190+
else
191+
Serial.println("Error resetting UM980 to factory defaults");
192+
193+
Serial.println("Waiting for UM980 to reboot");
194+
195+
while (1)
196+
{
197+
delay(1000); //Wait for device to reboot
198+
if (myGNSS.isConnected() == true)
199+
break;
200+
Serial.println("Device still rebooting");
201+
}
202+
203+
Serial.println("UM980 has completed reset");
204+
}
205+
206+
//----------------------------------------
207+
// Support Routines
208+
//----------------------------------------
209+
210+
// Display the contents of a buffer
211+
void dumpBuffer(const uint8_t *buffer, uint16_t length)
212+
{
213+
int bytes;
214+
const uint8_t *end;
215+
int index;
216+
char line[128];
217+
uint16_t offset;
218+
219+
end = &buffer[length];
220+
offset = 0;
221+
while (buffer < end)
222+
{
223+
// Determine the number of bytes to display on the line
224+
bytes = end - buffer;
225+
if (bytes > (16 - (offset & 0xf)))
226+
bytes = 16 - (offset & 0xf);
227+
228+
// Display the offset
229+
sprintf(line, "0x%08lx: ", offset);
230+
231+
// Skip leading bytes
232+
for (index = 0; index < (offset & 0xf); index++)
233+
sprintf(&line[strlen(line)], " ");
234+
235+
// Display the data bytes
236+
for (index = 0; index < bytes; index++)
237+
sprintf(&line[strlen(line)], "%02x ", buffer[index]);
238+
239+
// Separate the data bytes from the ASCII
240+
for (; index < (16 - (offset & 0xf)); index++)
241+
sprintf(&line[strlen(line)], " ");
242+
sprintf(&line[strlen(line)], " ");
243+
244+
// Skip leading bytes
245+
for (index = 0; index < (offset & 0xf); index++)
246+
sprintf(&line[strlen(line)], " ");
247+
248+
// Display the ASCII values
249+
for (index = 0; index < bytes; index++)
250+
sprintf(&line[strlen(line)], "%c", ((buffer[index] < ' ') || (buffer[index] >= 0x7f)) ? '.' : buffer[index]);
251+
Serial.println(line);
252+
253+
// Set the next line of data
254+
buffer += bytes;
255+
offset += bytes;
256+
}
257+
}
258+
259+
// Print the error message every 15 seconds
260+
void reportFatalError(const char *errorMsg)
261+
{
262+
while (1)
263+
{
264+
Serial.print("HALTED: ");
265+
Serial.print(errorMsg);
266+
Serial.println();
267+
sleep(15);
268+
}
269+
}
270+
271+
//----------------------------------------
272+
// Parser Support Routines
273+
//----------------------------------------
274+
275+
// Call back from within parser, for end of message
276+
// Process a complete message incoming from parser
277+
void processMessage(SEMP_PARSE_STATE *parse, uint16_t type)
278+
{
279+
SEMP_SCRATCH_PAD *scratchPad = (SEMP_SCRATCH_PAD *)parse->scratchPad;
280+
char *typeName;
281+
282+
// Dump the received messages
283+
if (!COMPILE_CAPTURE_RAW_DATA_STREAM)
284+
{
285+
// Display any invalid data
286+
if (offset > parse->length)
287+
{
288+
Serial.println();
289+
Serial.println("Unknown data");
290+
dumpBuffer(invalidCharacterBuffer, offset - parse->length);
291+
}
292+
offset = 0;
293+
294+
// Display the raw message
295+
// The type value is the index into the raw data array
296+
Serial.println();
297+
Serial.printf("Valid %s message: 0x%04x (%d) bytes\r\n",
298+
parserNames[type], parse->length, parse->length);
299+
dumpBuffer(parse->buffer, parse->length);
300+
}
301+
}
302+
303+
// Translate the state value into an ASCII state name
304+
const char *getParseStateName(SEMP_PARSE_STATE *parse)
305+
{
306+
const char *name;
307+
308+
do
309+
{
310+
name = sempNmeaGetStateName(parse);
311+
if (name)
312+
break;
313+
name = sempRtcmGetStateName(parse);
314+
if (name)
315+
break;
316+
name = sempUnicoreGetStateName(parse);
317+
if (name)
318+
break;
319+
name = sempGetStateName(parse);
320+
} while (0);
321+
return name;
322+
}
323+
324+
//----------------------------------------
325+
// Raw Data Stream Support Routines
326+
//----------------------------------------
327+
328+
// Add a comment to the end of the line with the data offset
329+
void convertToCComment(bool lastLine)
330+
{
331+
static uint32_t lastOffset;
332+
333+
uint32_t bytesOnLine;
334+
bool done;
335+
uint32_t nextOffset;
336+
uint32_t startOffset;
337+
338+
// Determine the various offsets
339+
340+
done = lastLine;
341+
nextOffset = dataOffset;
342+
bytesOnLine = nextOffset - lastOffset;
343+
lastOffset = dataOffset;
344+
if (bytesOnLine)
345+
done = false;
346+
if (!done)
347+
{
348+
// Determine the offset for the unfinished line
349+
startOffset = nextOffset - bytesOnLine;
350+
351+
// Add spaces to align the comments
352+
while (bytesOnLine++ < CONVERT_TO_C_BYTES_PER_LINE)
353+
Serial.print(" ");
354+
355+
// Add the end of line comment
356+
Serial.printf(" // 0x%08x (%d)\r\n", startOffset, startOffset);
357+
}
358+
359+
// Finish the data structure
360+
if (lastLine)
361+
{
362+
Serial.print("}; ");
363+
364+
// Add spaces to align the comments
365+
for (bytesOnLine = 0; bytesOnLine < CONVERT_TO_C_BYTES_PER_LINE; bytesOnLine++)
366+
Serial.print(" ");
367+
368+
// Add the end of line comment
369+
Serial.printf(" // 0x%08x (%d)\r\n", nextOffset, nextOffset);
370+
}
371+
}
372+
373+
// Add a data byte to the rawDataStream array, print the value in hex
374+
// Add an end of line comment with the offset from the beginning of the
375+
// buffer
376+
void convertToC(uint8_t data)
377+
{
378+
// Indent the line
379+
if (!(dataOffset & CONVERT_TO_C_BYTES_PER_MASK))
380+
Serial.print(" ");
381+
382+
// Add the data byte
383+
Serial.printf(" 0x%02x,", data);
384+
dataOffset += 1;
385+
386+
// Add the comment at the end of the line
387+
if (!(dataOffset & CONVERT_TO_C_BYTES_PER_MASK))
388+
convertToCComment(false);
389+
}

0 commit comments

Comments
 (0)