NMEA parser, well maybe GPS reader - my attempt

Hi all,
below is my attempt at basis for NMEA parser - actually code below just reads desired NMEA sentences...
I am not trying too reinvent the wheel, as I know many others have already done this - and I used Jordi's and Michal B.'s code for learning and reference. I just wanted to write my own, as to really understand the problem and what is needed (if I have to solve it I need to understand it :) ). I might , or might not use this for my future plans.

From what I can tell, IF I understood Jordi's and Michal's code, major difference is that while reading data from gps, I only "fill" gps data buffer if I am reading NMEA sentance I want - RMC and GGA; ther is no buffering of data for GLL, GSA, GSV, etc.
This is accomplished by, once start buffer flag is received, I scan buffer while it's being filled when it has only 5 entries. If protocol header is not RMC or GGA, buffer filling stops - thought behind this is potential performance as array (buffer) is not manipulated. Any array manipulation is done only when wanted protocol headers are being received, or for a short time while protocol header is being checked; otherwise code goes only through very short checking to see if received data is preamble $ (still no array manipulation). Switch / case statement is and 'break' option utilized ....

I am looking for critique on the method - and please be brutally honest; also is there any merit to this approach, etc. (just remember this is skeleton and not full parser, and some other stuff missing as not to complicate things now (such as buffer overflow check, etc.))

P.S. formatting got messed up once posted ..it was easier to read before in dev environment

//gps GPS reader attempt by automatik

char gps_raw_data; // incoming data from gps
char gps_buffer[90]; // buffer for gps data
char head_rmc[]="GPRMC"; //GPS NMEA header to look for
char head_gga[]="GPGGA"; //GPS NMEA header to look for
byte gps_counter=0; //counter for gps buffer
byte gps_data_into_buf_ok=1; //flag for gps buffer

void setup()
Serial.begin(4800); // opens serial port, in future will set to higher rate

void loop()

//also do some other stuff in future

void gps_data2(void)
while(Serial.available() > 0)
gps_raw_data = Serial.read();

switch (gps_data_into_buf_ok)
case 0: //gps buffer closed (not opened for filling) - should we open it?
if (gps_raw_data == '$') //if eq to '$' it's start of NMEA sentence
{ // so
gps_data_into_buf_ok=1; // set flag to strat filling gps buffer

//Serial.println("Buffer closed - nothing written");
//do nothing - buffer not open and it's not start of NMEA sentence
//nothing written to buffer array
break; //let's exit as there is no need to evaluate further

case 1: //buffer opened for filling - what shold we do with it?
gps_buffer[gps_counter] = gps_raw_data;

if (gps_counter == 4) //buffer is not full yet
// but let's test to see if we are getting NMEA sentence we want
//if we are we keep filling, if not we'll close buffer
{ //see if we are getting RMC or GGA sentences
if ((strncmp (gps_buffer,head_rmc,5) == 0) || (strncmp (gps_buffer,head_gga,5) == 0))
{//everything fine - we sre reading NMEA sentences we want
gps_counter++; //so let's increase counter
break; //and exit and advance to another data read since
//since this is not end of sentence - it will not be only 5 char long
{ //not NEMA sentence we want so
gps_data_into_buf_ok=0; //let's close buffer
gps_counter = 0; //reset counter; not really necessary here but just for clarity
break; //and get out of here
//so gps counter is less then 4 and will be evaluated later
//or we are filling the buffer

if (gps_buffer[gps_counter] == 0x0A) // if data received is line feed (end of NMEA sentance)
//----------let's process buffer-------

//--print buffer---just for visualization ---
//uncomment next line to see ------

// here to be implemented - checksum, parsing out, etc

// buffer processed let's do some cleanup
for(int a=0; a<=gps_counter; a++) // reinitializing gps buffer
gps_counter=0; // Restarting the counter
gps_data_into_buf_ok=0; // close buffer as we are done processing
//and should be looking for start of new one
// found end of the gps NMEA sentence
{ // either valid buffer or still to be evaluated for desired NMEA sentence
//so advance counter

Views: 1649

Reply to This

Replies to This Discussion

By the way, you'll probably notice that it is a good idea to configure the GPS to spit only the needed sentences. It's what Chris proposed to do here with the Locosys GPS chip.
Thanks! I have EM-406A and I don't think it has that (cool) option....
yes the Em-406 can be configured with a program called SIRF demo , you can set baud and select which strings are sent , i did a parser for a PIC 18f4320 that printed LAT , LONG , and HEADING to a LCD display

i set the EM-406 with SIRFdemo so it only put out the $GPRMC string , this saved my program a ton of sorting as i only had to parse the one string for the info i wanted

i am sorry i don't have a link for SIRF demo , i downloaded it for free about 6 months ago , at the time i was able to find it with a google search , HTH
automatik: good approach, but it won't be any faster to only selectively "fill line buffer". You probably can't measure speed difference.
Rather concentrate on code size, this is what matters more on system with 14KB usable RAM. And you can measure code size.
i think this is a download link for SirfDemo


you can download sirfdemo from here also

and this is a good tutorial & GPS forum here

I have reset my EM406A to factory setting from sirfdemo. Thanks copperclad
hi Saiful
thank you for the link to SirfDemo , it is a great utility

Reply to Discussion


© 2020   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service