Ross, Here is the code to decode NMEA messages. It's not pretty but it's fast. It could be faster by inlining the check sum stuff. The weird union lets you look at the last 2 characters as an integer. Lets me use a faster switch instead of 2 if()'s. There is a hard coded offset for the check sum. I probably have time for the comparisons but I plan to use this in heavily loaded systems and every little bit helps. I assumed that the last 2 characters of the ID are enough to identify the message. It is not a safe assumption. A proprietary message could have the same to letters. I don't think any NEMA messages have the same last to characters in the identifier. I designed it to use NMEA messages to be NMEA compliant. If you switch GPS receivers you need to look and make sure it sends what you need. Making a NEMA compliant message is a good deal easier than making a NMEA compliant listener. This program is set up to run on Intel integers. It is test code that uses a file of MNEA captured data. If #define MOTOROLA it will work on Motorola processors. This is a quick hack to allow for the reversed bytes. It is not finished but it will get you along. It does do the check sums correctly. If you are interested I think I have the code to do Trimble ascii check sums also. I worked out enough to know that I can handle 4800 baud NEMA messages on an 68HC11 and still be able to do other things. The secret is to only look at the RS232 when you want a message. One will be by in a couple of seconds. Regards Gordon #include #define IBM #ifdef IBM #define OD 17487 /* $GPBOD,180.1,T,174.6,M,011,010*4A */ #define GA 16711 /* $GPGGA,200605,3607.564,N,09704.481,W,1,06,1.7,347.0,M,-26.3,M,,*79 */ #define LL 19532 /* $GPGLL,3607.563,N,09704.469,W,200627,A*3A */ #define MB 16973 /* $GPRMB,A,0.02,L,010,011,3607.537,N,09704.447,W,000.0,140.9,,A*1C */ #define MC 17229 /* $GPRMC,200607,A,3607.563,N,09704.480,W,000.0,095.1,010197,005.5,E*60 */ #define ME 17741 /* $PGRME,28.4,M,150.0,M,152.7,M*15 */ #define MM 19789 /* $PGRMM,WGS 84*06 */ #define MZ 23117 /* $PGRMZ,1120,f,3*29 */ #define PL 19536 /* $GPWPL,3607.564,N,09704.444,W,010*63 */ #define SA 16723 /* $GPGSA,A,3,,14,,18,,22,,,,,,,1.8,1.8,1.0*3F */ #define SV 22099 /* $GPGSV,2,1,08,03,31,125,32,14,33,209,34,16,43,247,46,18,44,313,41*73 */ #define TE 17748 /* $GPRTE,1,1,c,0,HOME,007,008,009,010,011,WRK*5D */ #end #IFDEF MOTOROLA #define OB 20292 /* $GPBOD,180.1,T,174.6,M,011,010*4A */ #define GA 18241 /* $GPGGA,200605,3607.564,N,09704.481,W,1,06,1.7,347.0,M,-26.3,M,,*79 */ #define LL 19532 /* $GPGLL,3607.563,N,09704.469,W,200627,A*3A */ #define SA 21313 /* $GPGSA,A,3,03,14,16,18,,22,29,,,,,,1.2,1.2,1.0*30 */ #define SV 21334 /* $GPGSV,2,1,08,03,31,125,32,14,33,209,34,16,43,247,46,18,44,313,41*73 */ #define MB 19778 /* $GPRMB,A,0.02,L,010,011,3607.537,N,09704.447,W,000.0,140.9,,A*1C */ #define ME 19781 /* $PGRME,28.4,M,150.0,M,152.7,M*15 */ #define MM 19789 /* $PGRMM,WGS 84*06 */ #define MZ 19802 /* $PGRMZ,1120,f,3*29 */ #endif #define DONOTHING #define TRUE 1 #define FALSE 0 int check_sum, good_message; union nema_msg { char s[81]; struct { char offset[4]; unsigned int id; } fudge; }; union nema_msg nema_m; int h2i(char c) { int v; switch(c) { case '0': v = 0; break; case '1': v = 1; break; case '2': v = 2; break; case '3': v = 3; break; case '4': v = 4; break; case '5': v = 5; break; case '6': v = 6; break; case '7': v = 7; break; case '8': v = 8; break; case '9': v = 9; break; case 'A': v = 10; break; case 'B': v = 11; break; case 'C': v = 12; break; case 'D': v = 13; break; case 'E': v = 14; break; case 'F': v = 15; break; } return(v); } int get_check_sum(char *s) { int t; t = h2i(s[0]) * 16 + h2i(s[1]); } int check_sum_ok(char *s) { check_sum = *s++; while(*s && *s !='*') check_sum ^= *s++; /* check_sum ^= *s;*/ return((good_message =(check_sum == get_check_sum(nema_m.s+44)) ? TRUE : FALSE)); } void main(int argc, char **argv) { char ns, ew, *lat, *lat_dec, *lon, *lon_dec, *s; int ilat, ilat_dec, ilon, ilon_dec; FILE *input; if(NULL==(input=fopen(argv[1],"r"))) { printf("bad file name >%s\n",argv[1]); exit(1); } while(!feof(input)) { fgets(&nema_m.s, 80, input); if(nema_m.s[0]=='$') /* beging of a good message */ if(nema_m.fudge.id== LL) /* dump any message but LL */ { check_sum_ok(nema_m.s); /* set global variable check_sum */ printf("A %d %s X %x",nema_m.fudge.id,nema_m.s, check_sum); /* $GPGLL,3607.563,N,09704.469,W,200627,A*3A */ s= nema_m.s+7; /* printf("*%s*\n",s);*/ lat = s; while(*s++ != '.') DONOTHING; *(s-1)=0; lat_dec = s; while(*s++ != ',') DONOTHING; *(s-1)=0; ns = *s; s = s + 2; lon = s; while(*s++ != '.') DONOTHING; *(s-1)=0; lon_dec = s; while(*s++ != ',') DONOTHING; *(s-1)=0; ew = *s; ilat = atoi(lat); ilat_dec = atoi(lat_dec); ilon = atoi(lon); ilon_dec = atoi(lon_dec); if(ns == 'S') ilat + ilat *-1; if(ew = 'W') ilon = ilon * -1; printf("B %03d.%3d %03d.%3d\n", ilat, ilat_dec, ilon, ilon_dec); nema_m.s[0] =0; /* erase $ may not be necessary */ } } }