| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /*
- * NMEA Wrapper for PC Compilation
- * Provides simplified NMEA parsing using main.h for PC compatibility
- */
- #define PC_BUILD
- #include "main.h"
- /* Prevent duplicate includes */
- #define _NMEA_H_ 1
- /* Helper function from nmea.c */
- static unsigned char nmea_checksum(const char *s) {
- unsigned char c = 0;
- while (*s && *s != '*') {
- c ^= *s;
- s++;
- }
- return c;
- }
- /* String comparison function from nmea.c */
- static char gp_comp(const char *s1, const char *s2) {
- while (*s1 && *s2) {
- if (*s1 != *s2)
- return *s1 - *s2;
- s1++;
- s2++;
- }
- if (*s1 == ',' && !*s2)
- return 0;
- return *s1 - *s2;
- }
- /* Forward declarations */
- static time_t gp_rmc_parse(const char *str);
- static void gp_gga_parse(const char *str);
- static void gp_vtg_parse(const char *str);
- /* Field extraction helper */
- static const char* get_field(const char **str, char *buf, size_t bufsize) {
- const char *s = *str;
- size_t i = 0;
- while (*s && *s != ',') s++;
- if (*s == ',') s++;
- while (*s && *s != ',' && *s != '*' && i < bufsize - 1) {
- buf[i++] = *s++;
- }
- buf[i] = '\0';
- *str = s;
- return buf;
- }
- /* Parse time from NMEA */
- static time_t parse_time(const char *timestr, const char *datestr) {
- struct tm t = {0};
- if (strlen(timestr) >= 6) {
- t.tm_hour = (timestr[0] - '0') * 10 + (timestr[1] - '0');
- t.tm_min = (timestr[2] - '0') * 10 + (timestr[3] - '0');
- t.tm_sec = (timestr[4] - '0') * 10 + (timestr[5] - '0');
- }
- if (strlen(datestr) >= 6) {
- t.tm_mday = (datestr[0] - '0') * 10 + (datestr[1] - '0');
- t.tm_mon = (datestr[2] - '0') * 10 + (datestr[3] - '0') - 1;
- t.tm_year = (datestr[4] - '0') * 10 + (datestr[5] - '0') + 100;
- }
- return mktime(&t);
- }
- /* Parse coordinate */
- static float parse_coord(const char *coord, const char *dir) {
- float deg, min;
- char *p;
- deg = strtof(coord, &p);
- if (!p || p == coord) return 0.0;
- min = fmodf(deg, 100.0f);
- deg = floorf(deg / 100.0f);
- float result = deg + min / 60.0f;
- if (*dir == 'S' || *dir == 'W')
- result = -result;
- return result;
- }
- /* RMC parser */
- static time_t gp_rmc_parse(const char *str) {
- char buf[32];
- const char *p = str;
- char timestr[16] = "", datestr[16] = "", status[2] = "";
- char lat[16] = "", latdir[2] = "", lon[16] = "", londir[2] = "";
- while (*p && *p != ',') p++;
- get_field(&p, timestr, sizeof(timestr));
- get_field(&p, status, sizeof(status));
- get_field(&p, lat, sizeof(lat));
- get_field(&p, latdir, sizeof(latdir));
- get_field(&p, lon, sizeof(lon));
- get_field(&p, londir, sizeof(londir));
- get_field(&p, buf, sizeof(buf)); /* speed */
- get_field(&p, buf, sizeof(buf)); /* course */
- get_field(&p, datestr, sizeof(datestr));
- if (status[0] == 'A') {
- location.lat = parse_coord(lat, latdir);
- location.lon = parse_coord(lon, londir);
- utc = parse_time(timestr, datestr);
- location.time = utc;
- return utc;
- }
- return 0;
- }
- /* GGA parser */
- static void gp_gga_parse(const char *str) {
- char buf[32];
- const char *p = str;
- char alt[16] = "", lat[16] = "", latdir[2] = "";
- char lon[16] = "", londir[2] = "";
- while (*p && *p != ',') p++;
- get_field(&p, buf, sizeof(buf)); /* time */
- get_field(&p, lat, sizeof(lat));
- get_field(&p, latdir, sizeof(latdir));
- get_field(&p, lon, sizeof(lon));
- get_field(&p, londir, sizeof(londir));
- get_field(&p, buf, sizeof(buf)); /* fix quality */
- get_field(&p, buf, sizeof(buf)); /* satellites */
- get_field(&p, buf, sizeof(buf)); /* HDOP */
- get_field(&p, alt, sizeof(alt));
- if (strlen(lat) > 0) {
- location.lat = parse_coord(lat, latdir);
- location.lon = parse_coord(lon, londir);
- }
- if (strlen(alt) > 0) {
- location.alt = atof(alt);
- }
- }
- /* VTG parser stub */
- static void gp_vtg_parse(const char *str) {
- (void)str;
- }
- /* Stub functions */
- void pmtk001_parse(const char *str) { (void)str; }
- void gps_initialize(void) {}
- void check_min_sat_limit(void) {}
- /* Main parse function */
- time_t gps_parse(const char *str) {
- signed int len = strlen(str) - 2;
- const char *checksum;
- unsigned char calc_checksum, inc_checksum;
- signed int i;
- char c;
- if (len < 4)
- return 0;
- for (i = len - 1; i && i >= (len - 2); i--) {
- if (str[i] == '*')
- break;
- }
- checksum = str + i + 1;
- inc_checksum = 0;
- while (*checksum && isalnum(*checksum)) {
- inc_checksum *= 16;
- c = *checksum++;
- if (c >= '0' && c <= '9') {
- inc_checksum += c - '0';
- } else if (c >= 'a' && c <= 'f') {
- inc_checksum += c - 'a' + 10;
- } else if (c >= 'A' && c <= 'F') {
- inc_checksum += c - 'A' + 10;
- } else {
- return 0;
- }
- }
- str++;
- calc_checksum = nmea_checksum(str);
- if (inc_checksum != calc_checksum) {
- xprintf("Invalid NMEA checksum: got %02X, expected %02X\n",
- inc_checksum, calc_checksum);
- return 0;
- }
- if (!gp_comp(str, "GPRMC") || !gp_comp(str, "GNRMC") ||
- !gp_comp(str, "BDRMC") || !gp_comp(str, "GARMC")) {
- return gp_rmc_parse(str);
- }
- if (!gp_comp(str, "GPGGA") || !gp_comp(str, "GNGGA") ||
- !gp_comp(str, "BDGGA") || !gp_comp(str, "GAGGA")) {
- gp_gga_parse(str);
- return 0;
- }
- if (!gp_comp(str, "GPVTG") || !gp_comp(str, "GNVTG")) {
- gp_vtg_parse(str);
- return 0;
- }
- return 0;
- }
- UINT get_line(char *buff, UINT sz_buf) {
- (void)buff;
- (void)sz_buf;
- return 0;
- }
|