[Firebug-cvs] fireboard/sensors/leadtek9546 .cvsignore,NONE,1.1 ggaparse.c,NONE,1.1 gllparse.c,NONE,
Brought to you by:
doolin
From: David M. D. <do...@us...> - 2004-08-30 17:03:08
|
Update of /cvsroot/firebug/fireboard/sensors/leadtek9546 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6892 Added Files: .cvsignore ggaparse.c gllparse.c gsvparse.c mssparse.c nmea_parse.c nmea_parse.h nsew.c packer.c rmcparse.c vtgparse.c Log Message: nmea parsing code written in c added to enable testing of functionality when the c code implemented in nesc. --- NEW FILE: .cvsignore --- *.stackdump --- NEW FILE: gsvparse.c --- #include <stdio.h> #include <stdlib.h> #include <memory.h> #include "nmea_parse.h" #include "leadtek_9546.h" GSV_Data * nmea_gsv_new(void) { GSV_Data * gsv_data; gsv_data = (GSV_Data*)malloc(sizeof(GSV_Data)); memset(gsv_data,0xda,sizeof(GSV_Data)); return gsv_data; } void nmea_gsv_delete(GSV_Data * gsv_data) { memset((void*)gsv_data,0xdd,sizeof(GSV_Data)); free(gsv_data); } void nmea_gsv_print(const GSV_Data * gsv_data) { int i; printf("Num messages: %d\n",gsv_data->num_messages); printf("Message number: %d\n",gsv_data->message_number); printf("Satellites in view: %d\n",gsv_data->satellites_in_view); for (i=0; i<4; i++) { printf("sat id: %d\n",gsv_data->channel[i].sat_id); printf("elevation: %d\n",gsv_data->channel[i].elevation); printf("azimuth: %d\n",gsv_data->channel[i].azimuth); printf("SNR: %d\n",gsv_data->channel[i].SNR); } } #define find_next_field_m(foo) while (*foo != ',') foo++;foo++ #define char_to_int_m(foo) (*foo-'0') #define extract_sats_in_view_m(foo) (10*(foo[0]-'0') + (foo[1]-'0')) #define extract_sat_number_m(foo) (10*(foo[0]-'0') + (foo[1]-'0')) #define extract_azimuth_m(foo) (100*(foo[0]-'0') + 10*(foo[1]-'0') + (foo[2]-'0')) GSV_Data * nmea_gsv_parse(const char * gsv_string) { GSV_Data * gsv_data = nmea_gsv_new(); const char * p = gsv_string; int i; uint8_t num_sats,mess_num; uint8_t numchannels; find_next_field_m(p); gsv_data->num_messages = char_to_int_m(p); find_next_field_m(p); mess_num = char_to_int_m(p); gsv_data->message_number = mess_num; find_next_field_m(p); num_sats = extract_sats_in_view_m(p); gsv_data->satellites_in_view = num_sats; // This is convenient for determining how many // channels to parse. if (mess_num*4 < num_sats) { numchannels = 4; } else { numchannels = num_sats % 4; } for (i=0; i<numchannels; i++) { find_next_field_m(p); gsv_data->channel[i].sat_id = extract_sat_number_m(p); find_next_field_m(p); gsv_data->channel[i].elevation = extract_sat_number_m(p); find_next_field_m(p); gsv_data->channel[i].azimuth = extract_azimuth_m(p); find_next_field_m(p); gsv_data->channel[i].SNR = extract_sat_number_m(p); } return gsv_data; } --- NEW FILE: packer.c --- // Some macros for packing floats into uint16s #include <stdio.h> typedef struct { uint8_t hours; //Hours uint8_t minutes;//Minutes uint8_t Lat_deg;//Latitude degrees uint8_t Long_deg;//Longitude degrees uint32_t dec_sec;//Decimal seconds uint32_t Lat_dec_min;//Latitude decimal minutes uint32_t Long_dec_min;//Longitude decimal minutes uint8_t NSEWind;//NSEWind uint8_t Fixed; // as to whether the packet is valid(i.e. has the gps Fixed on to the sattelites). } XSensorMTS420GPSData1; typedef struct { uint8_t hours; //Hours uint8_t minutes;//Minutes uint32_t dec_sec;//Decimal seconds uint8_t Lat_deg;//Latitude degrees uint32_t Lat_dec_min;//Latitude decimal minutes uint8_t Long_deg;//Longitude degrees uint32_t Long_dec_min;//Longitude decimal minutes uint8_t NSEWind;//NSEWind uint8_t Fixed; // as to whether the packet is valid(i.e. has the gps Fixed on to the sattelites). } XSensorMTS420GPSData2; /* gps_uart->data[DEC_SEC] = temp&0xff; gps_uart->data[DEC_SEC+1] = (temp&0xff00)>>8; gps_uart->data[DEC_SEC+2] = (temp&0xff0000)>>16; gps_uart->data[DEC_SEC+3] = (temp&0xff000000)>>24; */ #define pack_4_bytes_m(ival,array) (array[0]=ival&0xff,array[1]&0xff00>>8,array[2]&0xff0000>>16,array[3]&0xff000000>>24) #define unpack_4_bytes(ival,array) (0) int main(int argc, char ** argv) { float fval = 32.33; uint32_t ival; uint8_t array[4] = {0xda}; typedef struct _floatbytes { float bytes; } floatbytes; floatbytes fb; floatbytes * pfb; pfb = &fb; ival = (uint32_t)(100*fval); printf("ival: %d\n",ival); //pack_4_bytes_m(ival,array); array[0]=ival&0xff; array[1]=ival&0xff00>>8; array[2]=ival&0xff0000>>16; array[3]=ival&0xff000000>>24; printf("Printing packed array: %f\n",*array/100.0); pfb = (floatbytes*)array; printf("Printing packed array: %f\n",pfb->bytes/100.0); printf("Sizeof struct1: %d\n",sizeof(XSensorMTS420GPSData1)); printf("Sizeof struct2: %d\n",sizeof(XSensorMTS420GPSData2)); return 0; } --- NEW FILE: rmcparse.c --- #include <stdio.h> #include <stdlib.h> #include <memory.h> #include "nmea_parse.h" #include "leadtek_9546.h" RMC_Data * nmea_rmc_new(void) { RMC_Data * rmc_data; rmc_data = (RMC_Data*)malloc(sizeof(RMC_Data)); memset(rmc_data,0x0,sizeof(RMC_Data)); return rmc_data; } void nmea_rmc_delete(RMC_Data * rmc_data) { memset((void*)rmc_data,0xdd,sizeof(RMC_Data)); free(rmc_data); } void nmea_rmc_print(const RMC_Data * rmc_data) { } RMC_Data * nmea_rmc_parse(const char * rmc_string) { RMC_Data * rmc_data = nmea_rmc_new(); //const char * p = rmc_string; return rmc_data; } --- NEW FILE: nsew.c --- /* Check out what bit masking does to certain chars. */ #include <stdio.h> int main(int argc, char ** argv) { printf("N: %d\n",'N'); printf("S: %d\n",'S'); printf("E: %d\n",'E'); printf("W: %d\n",'W'); printf("N & E: %d\n",'N'&'E'); printf("S & E: %d\n",'S'&'E'); printf("N & W: %d\n",'N'&'W'); printf("S & W: %d\n",'S'&'W'); return 0; } --- NEW FILE: ggaparse.c --- #include <stdio.h> #include <stdlib.h> #include <memory.h> #include "nmea_parse.h" #include "leadtek_9546.h" char * gga = "$GPGGA,231622.994,3751.3086,N,12216.5235,W,1,09,1.1,-4.5,M,,,,0000*30"; /* #define extract_num_sats_m(data) (10*(data[0]-'0') + (data[1]-'0')) #define extract_hours_m(data) (10*(data[0]-'0') + (data[1]-'0')) #define extract_minutes_m(data) (10*(data[2]-'0') + (data[3]-'0')) #define extract_dec_sec_m(data) (10*(data[4]-'0') + (data[5]-'0') + 0.1*(data[7]-'0') \ + 0.01*(data[8]-'0') \ + 0.001*(data[9]-'0')) #define extract_Lat_deg_m(data) (10*(data[0]-'0') + (data[1]-'0')) #define extract_Lat_dec_min_m(data) (10*(data[2]-'0') + (data[3]-'0') + 0.1*(data[5]-'0') \ + 0.01*(data[6]-'0') + 0.001*(data[7]-'0') + 0.0001*(data[8]-'0')) #define extract_Long_deg_m(data) (100*(data[0]-'0') + 10*(data[1]-'0') + (data[2]-'0')) #define extract_Long_dec_min_m(data) (10*(data[3]-'0') + (data[4]-'0') + 0.1*(data[6]-'0') \ + 0.01*(data[7]-'0') + 0.001*(data[8]-'0') + 0.0001*(data[9]-'0')) */ #define NS_m(foo) ((foo[28]=='N') ? 1 : 0) #define EW_m(foo) ((foo[41]=='W') ? 1 : 0) #define extract_NSEWind_m(foo) ((EW_m(foo)) | ((NS_m(foo))<<4)) int nmea_is_gga_string(const char * nmea_string) { if ((nmea_string[3] == 'G') & (nmea_string[4] == 'G') & (nmea_string[5] == 'A')) { return 1; } else { return 0; } } GGA_Data * nmea_gga_new(void) { GGA_Data * gga_data; gga_data = (GGA_Data*)malloc(sizeof(GGA_Data)); memset(gga_data,0xda,sizeof(GGA_Data)); return gga_data; } void nmea_gga_delete(GGA_Data * gga_data) { memset((void*)gga_data,0xdd,sizeof(GGA_Data)); free(gga_data); } /** These functions can be supplanted by the macros once everything is tested. */ static inline int extract_hours(char * data) { return (10*(data[0]-'0') + (data[1]-'0')); } static inline int extract_minutes(char * data) { return (10*(data[2]-'0') + (data[3]-'0')); } /** FIXME: Where is data[6]? The decimal point? */ static inline float extract_dec_sec(char * data) { float dec_secs; dec_secs = 10*(data[4]-'0') + (data[5]-'0') + 0.1*(data[7]-'0') + 0.01*(data[8]-'0') + 0.001*(data[9]-'0'); return dec_secs; } static inline int extract_Lat_deg(char * data) { return 10*(data[0]-'0') + (data[1]-'0'); } static inline float extract_Lat_dec_min(char * data) { float dec_min; dec_min = 10*(data[2]-'0') + (data[3]-'0') + 0.1*(data[5]-'0') + 0.01*(data[6]-'0') + 0.001*(data[7]-'0') + 0.0001*(data[8]-'0'); /* dec_min = 100000*(data[2]-'0') + 10000*(data[3]-'0') + 1000*(data[4]-'0') + 100*(data[5]-'0') + 10*(data[6]-'0') + (data[7]-'0'); */ return dec_min; } static inline int extract_Long_deg(char * data) { return (100*(data[0]-'0') + 10*(data[1]-'0') + (data[2]-'0')); } static inline float extract_Long_dec_min(char * data) { float dec_min; dec_min = 10*(data[3]-'0') + (data[4]-'0') + 0.1*(data[6]-'0') + 0.01*(data[7]-'0') + 0.001*(data[8]-'0') + 0.0001*(data[9]-'0'); /* dec_min = 100000*(data[3]-'0') + 10000*(data[4]-'0') + 1000*(data[5]-'0') + 100*(data[6]-'0') + 10*(data[7]-'0') + (data[8]-'0'); */ return dec_min; } static inline int extract_NSEWind(char * gga_data) { char NS, EW; // This would be a funky macro... NS = (gga_data[28] == 'N') ? 1 : 0; EW = (gga_data[41] == 'W') ? 1 : 0; return (EW | (NS<<4)); // eg. Status = 000N000E = 00010000 } static inline int extract_num_sats(char * data) { return (10*(data[0]-'0') + (data[1]-'0')); } // Later add a print function etc. void nmea_gga_print(const GGA_Data * gga_data) { printf("hours: %d\n",gga_data->hours); printf("minutes: %d\n",gga_data->minutes); printf("dec_sec: %f\n",gga_data->dec_sec); printf("Lat_deg: %d\n",gga_data->Lat_deg); printf("Lat_dec_min: %f\n",gga_data->Lat_dec_min); printf("Long_deg: %d\n",gga_data->Long_deg); printf("Long_dec_min: %f\n",gga_data->Long_dec_min); printf("Num sats: %d\n",gga_data->num_sats); printf("NSEWind: %d\n",gga_data->NSEWind); } /** @brief Parses an NMEA-0183 GGA string emitted by the * leadtek 9546 unit. This function was written to * support programming in TinyOS, where the character * to numerical conversion is performed by the macros. * Using this function, changes to the conversion macros * can be easily and safely tested. * * @param gga_string is the character array coming from the * the leadtek unit. * * @return Pointer to GGA_Data struct containing processed * values from the character array. * * @warning This function assumes that the values stored as * characters in the array have the same fixed numbers, * which allows offsets into the character array to be * hardcoded into the parsing function. This makes sense * for small devices such as microcontrollers. For a pc, * probably better to use atoi, atof, etc. * * @author David M. Doolin */ GGA_Data * nmea_gga_parse(const char * gga_string) { int i = 0; int numcommas = 0; int numsats = 0; const char * data; GGA_Data * ggad = nmea_gga_new(); while (numcommas < 7) { if (gga_string[i] == ',') { numcommas++; } i++; } numsats = (10*(gga_string[i]-'0') + (gga_string[i+1]-'0')); // Change all of these to do comma scanning, which will // make everything size independent. data = &gga_string[45]; ggad->num_sats = extract_num_sats_m(data); data = &gga_string[i]; numsats = extract_num_sats_m(data); data = &gga_string[7]; ggad->hours = extract_hours_m(data); data = &gga_string[7]; ggad->minutes = extract_minutes_m(data); data = &gga_string[7]; ggad->dec_sec = extract_dec_sec_m(data); data = &gga_string[18]; ggad->Lat_deg = extract_Lat_deg_m(data); data = &gga_string[18]; ggad->Lat_dec_min = extract_Lat_dec_min_m(data); data = &gga_string[30]; ggad->Long_deg = extract_Long_deg_m(data); data = &gga_string[30]; ggad->Long_dec_min = extract_Long_dec_min_m(data); ggad->NSEWind = extract_NSEWind_m(gga_string); return ggad; } // This can eventually be deleted. #ifdef STANDALONE void check_type(NMEA_Data * nmea_data) { } int main(int argc, char ** argv) { int i = 0; int numcommas = 0; int hours = 0; int minutes = 0; float dec_sec = 0; int Lat_deg = 0; float Lat_dec_min = 0; int Long_deg = 0; float Long_dec_min = 0; int numsats = 0; char * data; GGA_Data ggad; GLL_Data glld; nmea_get_type(gga); printf("Checking to see if the GGA macro works: %d\n", nmea_is_gga_string_m(gga)); while (numcommas < 7) { if (gga[i] == ',') { numcommas++; } i++; } numsats = (10*(gga[i]-'0') + (gga[i+1]-'0')); printf("num sats: %d\n",numsats); data = &gga[45]; numsats = extract_num_sats_m(data); printf("num sats: %d\n",numsats); data = &gga[i]; numsats = extract_num_sats_m(data); printf("num sats: %d\n",numsats); data = &gga[7]; hours = extract_hours_m(data); printf("hours: %d\n",hours); data = &gga[7]; minutes = extract_minutes_m(data); printf("minutes: %d\n",minutes); data = &gga[7]; dec_sec = extract_dec_sec_m(data); printf("dec_sec: %.3f\n",dec_sec); data = &gga[18]; Lat_deg = extract_Lat_deg_m(data); printf("Lat deg: %d\n", Lat_deg); data = &gga[18]; Lat_dec_min = extract_Lat_dec_min_m(data); printf("Lat dec min: %.4f\n",Lat_dec_min); data = &gga[30]; Long_deg = extract_Long_deg_m(data); printf("Long deg: %d\n", Long_deg); data = &gga[30]; Long_dec_min = extract_Long_dec_min_m(data); printf("Long dec min: %.4f\n",Long_dec_min); printf("sizeof GGA_Data: %d\n",sizeof(GGA_Data)); printf("sizeof GLL_Data: %d\n",sizeof(GLL_Data)); check_type((NMEA_Data*)&ggad); check_type((NMEA_Data*)&glld); return 0; } #endif /* STANDALONE */ --- NEW FILE: nmea_parse.h --- #ifndef NMEA_PARSE_H #define NMEA_PARSE_H #include <inttypes.h> /** @brief NMEA message parser which uses a lot of macros * and lower-level operations to extract data from the * character string comprising NMEA messages returned * from a GPS device. * * @todo RMC parser: Finish, check the test. * * @todo VTG parser, need to fix the test and get better * documentation for valid vtg type sentences because the * example provided in the LeadTek manual is not very good. * * @todo Move all the test strings to static const at the * head of the nmea_parse_test file so that the checksums * can all be verified. * * @todo Construct a framework for NMEA input messages used * to control the GPS device. */ /** @brief These are the most common NMEA-0183 sentences * all of which are available on the LeadTek 9546. * Other sentences can be added very easily. */ enum { GGA, GSV, GLL, GSA, RMC, VTG, MSS, UNKNOWN }; /** @brief Helpful macros, useful when only one or two particular * messages need to be extracted. If every NMEA sentence needs to * be processed, use the dispatch table instead of writing a * big if-else statement. White space is suppressed to keep * everything on one line. */ #define nmea_is_gga_string_m(ns) ((ns[3]=='G')&&(ns[4]=='G')&&(ns[5]=='A')) #define nmea_is_gsa_string_m(ns) ((ns[3]=='G')&&(ns[4]=='S')&&(ns[5]=='A')) #define nmea_is_gsv_string_m(ns) ((ns[3]=='G')&&(ns[4]=='S')&&(ns[5]=='V')) #define nmea_is_gll_string_m(ns) ((ns[3]=='G')&&(ns[4]=='L')&&(ns[5]=='L')) #define nmea_is_rmc_string_m(ns) ((ns[3]=='R')&&(ns[4]=='M')&&(ns[5]=='C')) #define nmea_is_vtg_string_m(ns) ((ns[3]=='V')&&(ns[4]=='T')&&(ns[5]=='G')) #define nmea_is_mss_string_m(ns) ((ns[3]=='M')&&(ns[4]=='S')&&(ns[5]=='S')) typedef struct nmea_data NMEA_Data; // 0 length for using in TinyOS interface // definitions. struct nmea_data { }; /** @brief The data encapsulated in an NMEA sentence * needs to be changed from character format to * appropriate type: int or float for time and * lat/long positions. For TOS applications, * incomplete types are rarely used, struct members * are accessed directly. For applications with * much faster cpu and more ram, these definitions * could be changed into incomplete types, and the * appropriate accessor methods written for support. * Currently, the mig message generator requires * messages to be defined as below to generate the * correct Java code. */ typedef struct gga_data { NMEA_Data nd; // Magic and mote_id could go into the NMEA_Data struct. //uint8_t magic; //uint16_t mote_id; uint8_t hours; uint8_t minutes; uint8_t Lat_deg; uint8_t Long_deg; float dec_sec; float Lat_dec_min; float Long_dec_min; uint8_t NSEWind; uint8_t num_sats; } GGA_Data; typedef struct gll_data { NMEA_Data nd; uint8_t Lat_deg; uint8_t Long_deg; uint8_t hours; uint8_t minutes; float Long_dec_min; float Lat_dec_min; float dec_sec; uint8_t NSEWind; char status; } GLL_Data; typedef struct gsa_data { NMEA_Data nd; uint8_t sat_used[12]; // These may be able to be stuffed into uint16_t, // depending on the precision the GPS unit reports. // Ask LeadTek or SiRF about this, but use float for // to get the code running. float PDOP; float HDOP; float VDOP; char mode1; uint8_t mode2; } GSA_Data; typedef struct _gsv_channel { uint8_t sat_id; uint8_t elevation; uint16_t azimuth; uint8_t SNR; } gsv_channel; typedef struct gsv_data { NMEA_Data nd; uint8_t num_messages; uint8_t message_number; uint8_t satellites_in_view; gsv_channel channel[4]; } GSV_Data; typedef struct rmc_data { NMEA_Data nd; } RMC_Data; typedef struct vtg_data { NMEA_Data nd; float course_true; float course_mag; float speed_knots; float speed_kph; } VTG_Data; typedef struct mss_data { NMEA_Data nd; uint8_t signal_strength; uint8_t SNR; uint16_t bit_rate; float beacon_freq; } MSS_Data; int nmea_get_type (const char * nmeastring); GGA_Data * nmea_gga_new (void); GLL_Data * nmea_gll_new (void); GSA_Data * nmea_gsa_new (void); GSV_Data * nmea_gsv_new (void); RMC_Data * nmea_rmc_new (void); VTG_Data * nmea_vtg_new (void); MSS_Data * nmea_mss_new (void); void nmea_gga_delete (GGA_Data * gga_data); void nmea_gll_delete (GLL_Data * gll_data); void nmea_gsa_delete (GSA_Data * gsa_data); void nmea_gsv_delete (GSV_Data * gsv_data); void nmea_rmc_delete (RMC_Data * rmc_data); void nmea_vtg_delete (VTG_Data * vtg_data); void nmea_mss_delete (MSS_Data * mss_data); GGA_Data * nmea_gga_parse (const char * gga_string); GLL_Data * nmea_gll_parse (const char * gll_string); GSA_Data * nmea_gsa_parse (const char * gsa_string); GSV_Data * nmea_gsv_parse (const char * gsv_string); RMC_Data * nmea_rmc_parse (const char * rmc_string); VTG_Data * nmea_vtg_parse (const char * vtg_string); MSS_Data * nmea_mss_parse (const char * mss_string); void nmea_gga_print (const GGA_Data * gga_data); void nmea_gll_print (const GLL_Data * gll_data); void nmea_gsa_print (const GSA_Data * gsa_data); void nmea_gsv_print (const GSV_Data * gsv_data); void nmea_mss_print (const MSS_Data * mss_data); int test_gga_parse (void); int test_gll_parse (void); int test_gsa_parse (void); int test_gsv_parse (void); int test_rmc_parse (void); int test_vtg_parse (void); int test_mss_parse (void); #endif /* NMEA_PARSE_H */ --- NEW FILE: mssparse.c --- #include <stdio.h> #include <stdlib.h> #include <memory.h> #include "nmea_parse.h" #include "leadtek_9546.h" MSS_Data * nmea_mss_new(void) { MSS_Data * mss_data; mss_data = (MSS_Data*)malloc(sizeof(MSS_Data)); memset(mss_data,0x0,sizeof(MSS_Data)); return mss_data; } void nmea_mss_delete(MSS_Data * mss_data) { memset((void*)mss_data,0xdd,sizeof(MSS_Data)); free(mss_data); } void nmea_mss_print(const MSS_Data * mss_data) { printf("Signal strength: %d\n",mss_data->signal_strength); printf("SNR: %d\n",mss_data->SNR); printf("Beacon freq: %f\n",mss_data->beacon_freq); printf("Bit rate: %d\n",mss_data->bit_rate); } #define find_next_field_m(foo) while (*foo != ',')foo++;foo++ #define extract_signal_strength_m(foo) (10*(foo[0]-'0') + (foo[1]-'0')) #define extract_SNR_m(foo) (10*(foo[0]-'0') + (foo[1]-'0')) #define extract_beacon_freq_m(foo) ((100*(foo[0]-'0')) \ +(10*(foo[1]-'0')) \ +(foo[2]-'0') \ +(0.1*(foo[4]-'0'))) #define extract_bit_rate_m(foo) ((100*(foo[0]-'0')) \ +(10*(foo[1]-'0')) \ +(foo[2]-'0')) MSS_Data * nmea_mss_parse(const char * mss_string) { MSS_Data * mss_data = nmea_mss_new(); const char * p = mss_string; find_next_field_m(p); mss_data->signal_strength = extract_signal_strength_m(p); find_next_field_m(p); mss_data->SNR = extract_SNR_m(p); find_next_field_m(p); mss_data->beacon_freq = extract_beacon_freq_m(p); find_next_field_m(p); mss_data->bit_rate = extract_bit_rate_m(p); return mss_data; } --- NEW FILE: nmea_parse.c --- #include <stdio.h> #include "nmea_parse.h" /** @brief This is a pretty small struct, should * not be too overwhelming even on a really * small device like a mica2. For a large * device where function pointers are supported, * a 3rd field for the appropriate function * * should be added. */ typedef struct nmea_types { char * nmea_type; unsigned char tag; } NMEA_Types; /** @brief These are the most common NMEA sentences, and what are * supported on the LeadTek 9546. */ NMEA_Types nt[] = { {"GGA", GGA}, {"GLL", GLL}, {"GSA", GSA}, {"GSV", GSV}, {"RMC", RMC}, {"VTG", VTG}, {NULL, 0 } }; /** @brief Scans the NMEA message type table, * returns an enum of the type of NMEA message. * The enum should be processed in the calling * function to handle actual parsing of the * message. * * @param nmeastring is the character array that * is emitted by the GPS unit. * * @return enum NMEA type for use by calling * function to invoke the appropriate parser for * the nmea sentence. */ int nmea_get_type(const char * nmeastring) { /** Advance the pointer to make it easier to * see how the characters in the incoming * nmea_string are compared to the characters * in the type table. */ const char * typestring = nmeastring + 3; int i = 0; while (nt[i].nmea_type != NULL) { char * type = nt[i].nmea_type; if ((typestring[0] == type[0]) && (typestring[1] == type[1]) && (typestring[2] == type[2])) { return nt[i].tag; } i++; } return UNKNOWN; } --- NEW FILE: vtgparse.c --- #include <stdio.h> #include <stdlib.h> #include <memory.h> #include "nmea_parse.h" #include "leadtek_9546.h" VTG_Data * nmea_vtg_new(void) { VTG_Data * vtg_data; vtg_data = (VTG_Data*)malloc(sizeof(VTG_Data)); memset(vtg_data,0xda,sizeof(VTG_Data)); return vtg_data; } void nmea_vtg_delete(VTG_Data * vtg_data) { memset((void*)vtg_data,0xdd,sizeof(VTG_Data)); free(vtg_data); } void nmea_vtg_print(const VTG_Data * vtg_data) { printf("course true: %f\n",vtg_data->course_true); } #define find_next_field_m(foo) while (*foo != ',')foo++;foo++ #define extract_course_true_m(foo) ((100*(foo[0]-'0')) \ +(10*(foo[1]-'0')) \ +(foo[2]-'0') \ +(0.1*(foo[4]-'0')) \ +(0.01*(foo[5]-'0'))) #define extract_course_mag_m(foo) (0) #define extract_speed_knots_m(foo) (0) #define extract_speed_kph_m(foo) (0) VTG_Data * nmea_vtg_parse(const char * vtg_string) { VTG_Data * vtg_data = nmea_vtg_new(); const char * p = vtg_string; find_next_field_m(p); vtg_data->course_true = extract_course_true_m(p); find_next_field_m(p); // Skip the Reference, already know its true. find_next_field_m(p); if (*p != ',') { vtg_data->course_mag = extract_course_mag_m(p); } find_next_field_m(p); find_next_field_m(p); vtg_data->speed_knots = extract_speed_knots_m(p); find_next_field_m(p); find_next_field_m(p); vtg_data->speed_kph = extract_speed_kph_m(p); return vtg_data; } --- NEW FILE: gllparse.c --- #include <stdio.h> #include <stdlib.h> #include <memory.h> #include "nmea_parse.h" #include "leadtek_9546.h" /** These macros are used for extracting data from the * LeadTek 9546 model, and may not be useful for other * GPS units. Check the output of each GPS unit carefully * for the number of digits in each field. */ // Start with defining the offsets. #define LAT_DEG 7 #define LAT_DEC_MIN 9 #define NS_IND 17 #define LONG_DEG 19 #define LONG_DEC_MIN 21 #define EW_IND 30 #define HOURS 32 #define STATUS 43 #define NS_m(foo) ((foo[NS_IND]=='N') ? 1 : 0) #define EW_m(foo) ((foo[EW_IND]=='W') ? 1 : 0) #define extract_NSEWind_m(foo) ((EW_m(foo)) | ((NS_m(foo))<<4)) static const char gll_test_string[] = {"$GPGLL,3723.2475,N,12158.3416,W,161229.487,A*2C"}; #define extract_long_m(data) (1) GLL_Data * nmea_gll_new(void) { GLL_Data * gll_data; gll_data = (GLL_Data*)malloc(sizeof(GLL_Data)); memset(gll_data,0xda,sizeof(GLL_Data)); return gll_data; } void nmea_gll_delete(GLL_Data * gll_data) { memset((void*)gll_data,0xdd,sizeof(GLL_Data)); free(gll_data); } void nmea_gll_print(const GLL_Data * gll_data) { printf("Lat deg: %d\n",gll_data->Lat_deg); printf("Lat dec min: %f\n",gll_data->Lat_dec_min); printf("Long deg: %d\n",gll_data->Long_deg); printf("Long dec min: %f\n",gll_data->Long_dec_min); printf("Hours: %d\n",gll_data->hours); printf("Minutes: %d\n",gll_data->minutes); printf("Seconds: %f\n",gll_data->dec_sec); printf("NSEWind: %d\n",gll_data->NSEWind); printf("Status: %c\n",gll_data->status); } GLL_Data * nmea_gll_parse(const char * gll_string) { GLL_Data * gll_data = nmea_gll_new(); const char * data; data = &gll_string[LAT_DEG]; gll_data->Lat_deg = extract_Lat_deg_m(data); gll_data->Lat_dec_min = extract_Lat_dec_min_m(data); data = &gll_string[LONG_DEG]; gll_data->Long_deg = extract_Long_deg_m(data); gll_data->Long_dec_min = extract_Long_dec_min_m(data); data = &gll_string[HOURS]; gll_data->hours = extract_hours_m(data); gll_data->minutes = extract_minutes_m(data); gll_data->dec_sec = extract_dec_sec_m(data); gll_data->status = gll_string[STATUS]; gll_data->NSEWind = extract_NSEWind_m(gll_string); return gll_data; } #ifdef STANDALONE int main(int argc, char ** argv) { const char gll_string[] = {"foo"}; nmea_gll_parse(gll_string); return 0; } #endif |