Skip to content

Commit 61a4c65

Browse files
committed
Add SBF invalidDataCallback
1 parent a108cf4 commit 61a4c65

File tree

3 files changed

+64
-26
lines changed

3 files changed

+64
-26
lines changed

examples/SBF_in_SPARTN_Test/SBF_in_SPARTN_Test.ino

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
SparkFun SBF in SPARTN test example sketch
2+
SparkFun SBF-in-SPARTN test example sketch
33
44
The mosaic-X5 can output raw L-Band (LBandBeam1) data, interspersed with SBF messages
55
6-
This example demonstrates how to use two parsers to extract the SBF from the L-Band stream
6+
This example demonstrates how to use two parsers to separate the SBF from the L-Band stream
7+
and extract SPARTN from the remaining raw L-Band
78
89
License: MIT. Please see LICENSE.md for more details
910
*/
@@ -109,7 +110,6 @@ const uint8_t rawDataStream[] =
109110

110111
uint32_t dataOffset1;
111112
SEMP_PARSE_STATE *parse1;
112-
uint32_t dataOffset2;
113113
SEMP_PARSE_STATE *parse2;
114114

115115
//----------------------------------------
@@ -133,36 +133,30 @@ void setup()
133133
if (!parse1)
134134
reportFatalError("Failed to initialize parser 1");
135135

136+
sempEnableDebugOutput(parse1); // Debug - comment if desired
137+
138+
// Add the callback for invalid SBF data,
139+
// to allow it to be passed to the SPARTN parser
140+
sempSbfSetInvalidDataCallback(parse1, invalidSbfData);
141+
136142
parse2 = sempBeginParser(parserTable2, parserCount2,
137143
parser2Names, parser2NameCount,
138144
0, BUFFER_LENGTH, processSpartnMessage, "SPARTN_Test");
139145
if (!parse2)
140146
reportFatalError("Failed to initialize parser 2");
141147

148+
sempEnableDebugOutput(parse2); // Debug - comment if desired
149+
142150
// Obtain a raw data stream from somewhere
143151
Serial.printf("Raw data stream: %d bytes\r\n", RAW_DATA_BYTES);
144152

145153
// The raw data stream is passed to the SBF parser one byte at a time
146-
sempEnableDebugOutput(parse1);
147-
148-
// Any data which is not SBF is passed to the SPARTN parser
149-
sempEnableDebugOutput(parse2);
150-
154+
// Any data which is not SBF is passed to the SPARTN parser via the callback
151155
for (dataOffset1 = 0; dataOffset1 < RAW_DATA_BYTES; dataOffset1++)
152156
{
153157
// Update the SBF parser state based on the incoming byte
158+
// Non-SBF data is parsed automatically by invalidSbfData
154159
sempParseNextByte(parse1, rawDataStream[dataOffset1]);
155-
156-
// If the data is not SBF, the state will return to sempFirstByte
157-
if (parse1->state == sempFirstByte)
158-
{
159-
// Data is not SBF, so pass it to the SPARTN parser
160-
for (dataOffset2 = 0; dataOffset2 < parse1->length; dataOffset2++)
161-
{
162-
// Update the SPARTN parser state based on the non-SBF byte
163-
sempParseNextByte(parse2, parse1->buffer[dataOffset2]);
164-
}
165-
}
166160
}
167161

168162
// Done parsing the data
@@ -176,6 +170,18 @@ void loop()
176170
// Nothing to do here...
177171
}
178172

173+
// Callback from within the SBF parser when invalid data is identified
174+
// The data is passed on to the SPARTN parser
175+
void invalidSbfData(SEMP_PARSE_STATE *parse)
176+
{
177+
// Data is not SBF, so pass it to the SPARTN parser
178+
for (uint32_t dataOffset = 0; dataOffset < parse->length; dataOffset++)
179+
{
180+
// Update the SPARTN parser state based on the non-SBF byte
181+
sempParseNextByte(parse2, parse->buffer[dataOffset]);
182+
}
183+
}
184+
179185
// Call back from within parser, for end of message
180186
// Process a complete message incoming from parser
181187
void processSbfMessage(SEMP_PARSE_STATE *parse, uint16_t type)
@@ -213,15 +219,13 @@ void processSpartnMessage(SEMP_PARSE_STATE *parse, uint16_t type)
213219
SEMP_SCRATCH_PAD *scratchPad = (SEMP_SCRATCH_PAD *)parse->scratchPad;
214220

215221
static bool displayOnce = true;
216-
uint32_t offset;
217222

218223
// Display the raw message
219224
Serial.println();
220-
offset = dataOffset2 + 1 - parse->length;
221-
Serial.printf("Valid SPARTN message, type %d, subtype %d : %d bytes at 0x%08lx (%ld)\r\n",
225+
Serial.printf("Valid SPARTN message, type %d, subtype %d : %d bytes\r\n",
222226
scratchPad->spartn.messageType,
223227
scratchPad->spartn.messageSubtype,
224-
parse->length, offset, offset);
228+
parse->length);
225229
dumpBuffer(parse->buffer, parse->length);
226230

227231
// Display the parser state

src/Parse_SBF.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ bool sempSbfReadBytes(SEMP_PARSE_STATE *parse, uint8_t data)
4545
parse->parserName,
4646
scratchPad->sbf.sbfID,
4747
parse->length, parse->length);
48+
49+
if (scratchPad->sbf.invalidDataCallback)
50+
scratchPad->sbf.invalidDataCallback(parse);
4851
}
4952

5053
return false;
@@ -68,12 +71,15 @@ bool sempSbfLengthMSB(SEMP_PARSE_STATE *parse, uint8_t data)
6871
parse->state = sempSbfReadBytes;
6972
return true;
7073
}
71-
74+
// else
7275
sempPrintf(parse->printDebug,
7376
"SEMP: %s SBF, 0x%04x (%d) bytes, length not modulo 4",
7477
parse->parserName,
7578
parse->length, parse->length);
7679

80+
if (scratchPad->sbf.invalidDataCallback)
81+
scratchPad->sbf.invalidDataCallback(parse);
82+
7783
parse->state = sempFirstByte;
7884
return false;
7985
}
@@ -150,12 +156,16 @@ bool sempSbfPreamble2(SEMP_PARSE_STATE *parse, uint8_t data)
150156
parse->state = sempSbfCRC1;
151157
return true;
152158
}
153-
159+
// else
154160
sempPrintf(parse->printDebug,
155161
"SEMP: %s SBF, 0x%04x (%d) bytes, invalid preamble2",
156162
parse->parserName,
157163
parse->length, parse->length);
158164

165+
SEMP_SCRATCH_PAD *scratchPad = (SEMP_SCRATCH_PAD *)parse->scratchPad;
166+
if (scratchPad->sbf.invalidDataCallback)
167+
scratchPad->sbf.invalidDataCallback(parse);
168+
159169
parse->state = sempFirstByte;
160170
return false;
161171
}
@@ -168,6 +178,10 @@ bool sempSbfPreamble(SEMP_PARSE_STATE *parse, uint8_t data)
168178
parse->state = sempSbfPreamble2;
169179
return true;
170180
}
181+
// else
182+
SEMP_SCRATCH_PAD *scratchPad = (SEMP_SCRATCH_PAD *)parse->scratchPad;
183+
if (scratchPad->sbf.invalidDataCallback)
184+
scratchPad->sbf.invalidDataCallback(parse);
171185
return false;
172186
}
173187

@@ -195,6 +209,13 @@ const char * sempSbfGetStateName(const SEMP_PARSE_STATE *parse)
195209
return nullptr;
196210
}
197211

212+
// Set the invalid data callback
213+
void sempSbfSetInvalidDataCallback(const SEMP_PARSE_STATE *parse, SEMP_INVALID_DATA_CALLBACK invalidDataCallback)
214+
{
215+
SEMP_SCRATCH_PAD *scratchPad = (SEMP_SCRATCH_PAD *)parse->scratchPad;
216+
scratchPad->sbf.invalidDataCallback = invalidDataCallback;
217+
}
218+
198219
// Get the Block Number
199220
uint16_t sempSbfGetBlockNumber(const SEMP_PARSE_STATE *parse)
200221
{

src/SparkFun_Extensible_Message_Parser.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ typedef bool (*SEMP_BAD_CRC_CALLBACK)(P_SEMP_PARSE_STATE parse); // Parser state
6363
typedef void (*SEMP_EOM_CALLBACK)(P_SEMP_PARSE_STATE parse, // Parser state
6464
uint16_t type); // Index into parseTable
6565

66+
// Invalid data callback:
67+
// This is parser-specific and should be added to the parser scrtachpad if
68+
// needed. Normally this routine pointer is set to nullptr. The parser calls
69+
// the invalidDataCallback routine when the data is recognised as invalid.
70+
// This allows an upper layer to pass the data to a second parser if needed.
71+
// This is useful when parsing SBF which is interspersed in raw SPARTN L-Band data.
72+
// Data is passed to the SBF parser first. Any data which is invalid SBF is passed
73+
// to a separate SPARTN parser via this callback.
74+
typedef void (*SEMP_INVALID_DATA_CALLBACK)(P_SEMP_PARSE_STATE parse); // Parser state
75+
6676
// Length of the sentence name array
6777
#define SEMP_NMEA_SENTENCE_NAME_BYTES 16
6878

@@ -136,6 +146,8 @@ typedef struct _SEMP_SBF_VALUES
136146
uint8_t sbfIDrev = 0;
137147
uint16_t length;
138148
uint16_t bytesRemaining;
149+
// Invalid data callback routine (parser-specific)
150+
SEMP_INVALID_DATA_CALLBACK invalidDataCallback = (SEMP_INVALID_DATA_CALLBACK)nullptr;
139151
} SEMP_SBF_VALUES;
140152

141153
// Overlap the scratch areas since only one parser is active at a time
@@ -325,7 +337,7 @@ uint16_t sempRtcmGetMessageNumber(const SEMP_PARSE_STATE *parse);
325337
// u-blox parse routines
326338
bool sempUbloxPreamble(SEMP_PARSE_STATE *parse, uint8_t data);
327339
const char * sempUbloxGetStateName(const SEMP_PARSE_STATE *parse);
328-
uint16_t sempUbloxGetMessageNumber(const SEMP_PARSE_STATE *parse);
340+
uint16_t sempUbloxGetMessageNumber(const SEMP_PARSE_STATE *parse); // |- Class (8 bits) -||- ID (8 bits) -|
329341

330342
// Unicore binary parse routines
331343
bool sempUnicoreBinaryPreamble(SEMP_PARSE_STATE *parse, uint8_t data);
@@ -346,6 +358,7 @@ uint8_t sempSpartnGetMessageType(const SEMP_PARSE_STATE *parse);
346358
// SBF parse routines
347359
bool sempSbfPreamble(SEMP_PARSE_STATE *parse, uint8_t data);
348360
const char * sempSbfGetStateName(const SEMP_PARSE_STATE *parse);
361+
void sempSbfSetInvalidDataCallback(const SEMP_PARSE_STATE *parse, SEMP_INVALID_DATA_CALLBACK invalidDataCallback);
349362
uint16_t sempSbfGetBlockNumber(const SEMP_PARSE_STATE *parse);
350363
uint8_t sempSbfGetBlockRevision(const SEMP_PARSE_STATE *parse);
351364
uint8_t sempSbfGetU1(const SEMP_PARSE_STATE *parse, uint16_t offset);

0 commit comments

Comments
 (0)