diff --git a/master/master/lib/trackuinoGPS/config.h b/master/master/lib/trackuinoGPS/config.h --- a/master/master/lib/trackuinoGPS/config.h +++ b/master/master/lib/trackuinoGPS/config.h @@ -23,7 +23,7 @@ // THIS IS THE TRACKUINO FIRMWARE CONFIGURATION FILE. YOUR CALLSIGN AND // OTHER SETTINGS GO HERE. // -// NOTE: all pins are Arduino based, not the Atmega chip. Mapping: +// NOTE: all pins are Arduino based, not the Atmega chip. Mapping: this could be an issue !! ?? // http://www.arduino.cc/en/Hacking/PinMapping // -------------------------------------------------------------------------- diff --git a/master/master/lib/trackuinoGPS/gps.c b/master/master/lib/trackuinoGPS/gps.c --- a/master/master/lib/trackuinoGPS/gps.c +++ b/master/master/lib/trackuinoGPS/gps.c @@ -1,19 +1,19 @@ /* trackuino copyright (C) 2010 EA5HAV Javi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ #include "config.h" #include "gps.h" @@ -35,55 +35,59 @@ static void parse_altitude(const char *t // Module types typedef void (*t_nmea_parser)(const char *token); -enum t_sentence_type { - SENTENCE_UNK, - SENTENCE_GGA, - SENTENCE_RMC -}; + // Module constants static const t_nmea_parser unk_parsers[] = { - parse_sentence_type, // $GPxxx + parse_sentence_type, // $GPxxx }; static const t_nmea_parser gga_parsers[] = { - NULL, // $GPGGA - parse_time, // Time - NULL, // Latitude - NULL, // N/S - NULL, // Longitude - NULL, // E/W - NULL, // Fix quality - NULL, // Number of satellites - NULL, // Horizontal dilution of position - parse_altitude, // Altitude - NULL, // "M" (mean sea level) - NULL, // Height of GEOID (MSL) above WGS84 ellipsoid - NULL, // "M" (mean sea level) - NULL, // Time in seconds since the last DGPS update - NULL // DGPS station ID number + NULL, // $GPGGA + parse_time, // Time + NULL, // Latitude + NULL, // N/S + NULL, // Longitude + NULL, // E/W + NULL, // Fix quality + NULL, // Number of satellites + NULL, // Horizontal dilution of position + parse_altitude, // Altitude + NULL, // "M" (mean sea level) + NULL, // Height of GEOID (MSL) above WGS84 ellipsoid + NULL, // "M" (mean sea level) + NULL, // Time in seconds since the last DGPS update + NULL // DGPS station ID number }; static const t_nmea_parser rmc_parsers[] = { - NULL, // $GPRMC - parse_time, // Time - parse_status, // A=active, V=void - parse_lat, // Latitude, - parse_lat_hemi, // N/S - parse_lon, // Longitude - parse_lon_hemi, // E/W - parse_speed, // Speed over ground in knots - parse_course, // Track angle in degrees (true) - NULL, // Date (DDMMYY) - NULL, // Magnetic variation - NULL // E/W + NULL, // $GPRMC + parse_time, // Time + parse_status, // A=active, V=void + parse_lat, // Latitude, + parse_lat_hemi, // N/S + parse_lon, // Longitude + parse_lon_hemi, // E/W + parse_speed, // Speed over ground in knots + parse_course, // Track angle in degrees (true) + NULL, // Date (DDMMYY) + NULL, // Magnetic variation + NULL // E/W }; + + static const int NUM_OF_UNK_PARSERS = (sizeof(unk_parsers) / sizeof(t_nmea_parser)); static const int NUM_OF_GGA_PARSERS = (sizeof(gga_parsers) / sizeof(t_nmea_parser)); static const int NUM_OF_RMC_PARSERS = (sizeof(rmc_parsers) / sizeof(t_nmea_parser)); +enum t_sentence_type { + SENTENCE_UNK, + SENTENCE_GGA, + SENTENCE_RMC +}; + // Module variables static t_sentence_type sentence_type = SENTENCE_UNK; static bool at_checksum = false; @@ -116,247 +120,280 @@ float gps_speed = 0; float gps_altitude = 0; // Module functions -unsigned char from_hex(char a) +/// convert hex to binary ?? +unsigned char from_hex(char a) { - if (a >= 'A' && a <= 'F') - return a - 'A' + 10; - else if (a >= 'a' && a <= 'f') - return a - 'a' + 10; - else if (a >= '0' && a <= '9') - return a - '0'; - else - return 0; + if (a >= 'A' && a <= 'F'){ + return a - 'A' + 10; + }else if (a >= 'a' && a <= 'f'){ + return a - 'a' + 10; + }else if (a >= '0' && a <= '9'){ + return a - '0'; + }else{ + return 0; + } } +/// determine what type of message is being sent ?? +/// we only send one message type so may not be needed void parse_sentence_type(const char *token) { - if (strcmp(token, "$GPGGA") == 0) { - sentence_type = SENTENCE_GGA; - } else if (strcmp(token, "$GPRMC") == 0) { - sentence_type = SENTENCE_RMC; - } else { - sentence_type = SENTENCE_UNK; - } + if (strcmp(token, "$GPGGA") == 0) { + sentence_type = SENTENCE_GGA; + } else if (strcmp(token, "$GPRMC") == 0) { + sentence_type = SENTENCE_RMC; + } else { + sentence_type = SENTENCE_UNK; + } } + void parse_time(const char *token) { - // Time can have decimals (fractions of a second), but we only take HHMMSS - strncpy(new_time, token, 6); - // Terminate string - new_time[6] = '\0'; - - new_seconds = - ((new_time[0] - '0') * 10 + (new_time[1] - '0')) * 60 * 60UL + - ((new_time[2] - '0') * 10 + (new_time[3] - '0')) * 60 + - ((new_time[4] - '0') * 10 + (new_time[5] - '0')); + // Time can have decimals (fractions of a second), but we only take HHMMSS + ///we prolly want the entire time (unix time) ?? + strncpy(new_time, token, 6); + // Terminate string + new_time[6] = '\0'; + + new_seconds = + ((new_time[0] - '0') * 10 + (new_time[1] - '0')) * 60 * 60UL + + ((new_time[2] - '0') * 10 + (new_time[3] - '0')) * 60 + + ((new_time[4] - '0') * 10 + (new_time[5] - '0')); } +/// not sure of exact purpose, besides the name... void parse_status(const char *token) { - // "A" = active, "V" = void. We shoud disregard void sentences - if (strcmp(token, "A") == 0) - active = true; - else - active = false; + // "A" = active, "V" = void. We should disregard void sentences + if (strcmp(token, "A") == 0){ + active = true; + }else{ + active = false; + } } +/// this is a vital function void parse_lat(const char *token) { - // Parses latitude in the format "DD" + "MM" (+ ".M{...}M") - char degs[3]; - if (strlen(token) >= 4) { - degs[0] = token[0]; - degs[1] = token[1]; - degs[2] = '\0'; - new_lat = atof(degs) + atof(token + 2) / 60; - } - // APRS-ready latitude - strncpy(new_aprs_lat, token, 7); - new_aprs_lat[7] = '\0'; + // Parses latitude in the format "DD" + "MM" (+ ".M{...}M") + /// not sure about the format... + char degs[3]; + if (strlen(token) >= 4) { + degs[0] = token[0]; + degs[1] = token[1]; + degs[2] = '\0'; + new_lat = atof(degs) + atof(token + 2) / 60; + } + // APRS-ready latitude + strncpy(new_aprs_lat, token, 7); + new_aprs_lat[7] = '\0'; } +/// if this is hemisphere it is not needed. we are in the north. void parse_lat_hemi(const char *token) { - if (token[0] == 'S') - new_lat = -new_lat; - new_aprs_lat[7] = token[0]; - new_aprs_lon[8] = '\0'; + if (token[0] == 'S'){ + new_lat = -new_lat; + } + new_aprs_lat[7] = token[0]; + new_aprs_lon[8] = '\0'; } +/// another vital function void parse_lon(const char *token) { - // Longitude is in the format "DDD" + "MM" (+ ".M{...}M") - char degs[4]; - if (strlen(token) >= 5) { - degs[0] = token[0]; - degs[1] = token[1]; - degs[2] = token[2]; - degs[3] = '\0'; - new_lon = atof(degs) + atof(token + 3) / 60; - } - // APRS-ready longitude - strncpy(new_aprs_lon, token, 8); - new_aprs_lon[8] = '\0'; + // Longitude is in the format "DDD" + "MM" (+ ".M{...}M") + /// again not sure of formatting... + char degs[4]; + if (strlen(token) >= 5) { + degs[0] = token[0]; + degs[1] = token[1]; + degs[2] = token[2]; + degs[3] = '\0'; + new_lon = atof(degs) + atof(token + 3) / 60; + } + // APRS-ready longitude + strncpy(new_aprs_lon, token, 8); + new_aprs_lon[8] = '\0'; } +/// if this is hemisphere it is not needed void parse_lon_hemi(const char *token) { - if (token[0] == 'W') - new_lon = -new_lon; - new_aprs_lon[8] = token[0]; - new_aprs_lon[9] = '\0'; + if (token[0] == 'W'){ + new_lon = -new_lon; + } + new_aprs_lon[8] = token[0]; + new_aprs_lon[9] = '\0'; } +/// we do not need to record speed void parse_speed(const char *token) { - new_speed = atof(token); + new_speed = atof(token); } +/// we do not need to record course void parse_course(const char *token) { - new_course = atof(token); + new_course = atof(token); } +/// will use this to validate pressure readings void parse_altitude(const char *token) { - new_altitude = atof(token); + new_altitude = atof(token); } // // Exported functions // +/// void zeroing of data. presumably to be called at start void gps_setup() { - strcpy(gps_time, "000000"); - strcpy(gps_aprs_lat, "0000.00N"); - strcpy(gps_aprs_lon, "00000.00E"); + strcpy(gps_time, "000000"); + strcpy(gps_aprs_lat, "0000.00N"); + strcpy(gps_aprs_lon, "00000.00E"); } - +/// MKa GPS transmission parser +void parse_gps_transmission(char c){ + // i think c is the most recent character of transmission and is constantly + // tested if terminal character. if terminal then do parse on previous transmission. + + // $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx + if(c == '\n') //end of transmission sentence. may need more checks + { + + } +} +/// process gps transmission bool gps_decode(char c) { - int ret = false; - - switch(c) { - case '\r': - case '\n': - // End of sentence + int ret = false; - if (num_tokens && our_checksum == their_checksum) { -#ifdef DEBUG_GPS - Serial.print(" (OK!) "); - Serial.print(millis()); -#endif - // Return a valid position only when we've got two rmc and gga - // messages with the same timestamp. - switch (sentence_type) { - case SENTENCE_UNK: - break; // Keeps gcc happy - case SENTENCE_GGA: - strcpy(gga_time, new_time); - break; - case SENTENCE_RMC: - strcpy(rmc_time, new_time); - break; - } + switch(c) { + case '\r': + case '\n': // End of sentence + if (num_tokens && our_checksum == their_checksum) { ///checksum is valid (good transmission) + #ifdef DEBUG_GPS + Serial.print(" (OK!) "); + Serial.print(millis()); + #endif + // Return a valid position only when we have two rmc and gga + // messages with the same timestamp. + switch (sentence_type) { + case SENTENCE_UNK: + break; // Keeps gcc happy + case SENTENCE_GGA: + strcpy(gga_time, new_time); + break; + case SENTENCE_RMC: + strcpy(rmc_time, new_time); + break; + } - // Valid position scenario: - // - // 1. The timestamps of the two previous GGA/RMC sentences must match. - // - // 2. We just processed a known (GGA/RMC) sentence. Suppose the - // contrary: after starting up this module, gga_time and rmc_time - // are both equal (they're both initialized to ""), so (1) holds - // and we wrongly report a valid position. - // - // 3. The GPS has a valid fix. For some reason, the Venus 634FLPX - // reports 24 deg N, 121 deg E (the middle of Taiwan) until a valid - // fix is acquired: - // - // $GPGGA,120003.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*69 (OK!) - // $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30 (OK!) - // $GPRMC,120003.000,V,2400.0000,N,12100.0000,E,000.0,000.0,280606,,,N*78 (OK!) - // $GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02 (OK!) + // Valid position scenario: + // + // 1. The timestamps of the two previous GGA/RMC sentences must match. + // + // 2. We just processed a known (GGA/RMC) sentence. Suppose the + // contrary: after starting up this module, gga_time and rmc_time + // are both equal (they're both initialized to ""), so (1) holds + // and we wrongly report a valid position. + // + // 3. The GPS has a valid fix. For some reason, the Venus 634FLPX + // reports 24 deg N, 121 deg E (the middle of Taiwan) until a valid + // fix is acquired: + // + // $GPGGA,120003.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*69 (OK!) + // $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30 (OK!) + // $GPRMC,120003.000,V,2400.0000,N,12100.0000,E,000.0,000.0,280606,,,N*78 (OK!) + // $GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02 (OK!) - if (sentence_type != SENTENCE_UNK && // Known sentence? - strcmp(gga_time, rmc_time) == 0 && // RMC/GGA times match? - active) { // Valid fix? - // Atomically merge data from the two sentences - strcpy(gps_time, new_time); - gps_seconds = new_seconds; - gps_lat = new_lat; - gps_lon = new_lon; - strcpy(gps_aprs_lat, new_aprs_lat); - strcpy(gps_aprs_lon, new_aprs_lon); - gps_course = new_course; - gps_speed = new_speed; - gps_altitude = new_altitude; - ret = true; - } - } -#ifdef DEBUG_GPS - if (num_tokens) - Serial.println(); -#endif - at_checksum = false; // CR/LF signals the end of the checksum - our_checksum = '$'; // Reset checksums - their_checksum = 0; - offset = 0; // Prepare for the next incoming sentence - num_tokens = 0; - sentence_type = SENTENCE_UNK; - break; - - case '*': - // Handle as ',', but prepares to receive checksum (ie. do not break) - at_checksum = true; - our_checksum ^= c; + if (sentence_type != SENTENCE_UNK && // Known sentence? + strcmp(gga_time, rmc_time) == 0 && // RMC/GGA times match? + active) { // Valid fix? + // Atomically merge data from the two sentences + strcpy(gps_time, new_time); + gps_seconds = new_seconds; + gps_lat = new_lat; + gps_lon = new_lon; + strcpy(gps_aprs_lat, new_aprs_lat); + strcpy(gps_aprs_lon, new_aprs_lon); + gps_course = new_course; + gps_speed = new_speed; + gps_altitude = new_altitude; + ret = true; + } + } + #ifdef DEBUG_GPS + if (num_tokens){ + Serial.println(); + } + #endif + at_checksum = false; // CR/LF signals the end of the checksum + our_checksum = '$'; // Reset checksums + their_checksum = 0; + offset = 0; // Prepare for the next incoming sentence + num_tokens = 0; + sentence_type = SENTENCE_UNK; + break; - case ',': - // Process token - token[offset] = '\0'; - our_checksum ^= c; // Checksum the ',', undo the '*' + case '*': + // Handle as ',', but prepares to receive checksum (ie. do not break) + at_checksum = true; + our_checksum ^= c; + + case ',': + // Process token + token[offset] = '\0'; + our_checksum ^= c; // Checksum the ',', undo the '*' - // Parse token - switch (sentence_type) { - case SENTENCE_UNK: - if (num_tokens < NUM_OF_UNK_PARSERS && unk_parsers[num_tokens]) - unk_parsers[num_tokens](token); - break; - case SENTENCE_GGA: - if (num_tokens < NUM_OF_GGA_PARSERS && gga_parsers[num_tokens]) - gga_parsers[num_tokens](token); - break; - case SENTENCE_RMC: - if (num_tokens < NUM_OF_RMC_PARSERS && rmc_parsers[num_tokens]) - rmc_parsers[num_tokens](token); - break; - } + // Parse token + switch (sentence_type) { + case SENTENCE_UNK: + if (num_tokens < NUM_OF_UNK_PARSERS && unk_parsers[num_tokens]){ + unk_parsers[num_tokens](token); + } + break; + case SENTENCE_GGA: + if (num_tokens < NUM_OF_GGA_PARSERS && gga_parsers[num_tokens]){ + gga_parsers[num_tokens](token); + } + break; + case SENTENCE_RMC: + if (num_tokens < NUM_OF_RMC_PARSERS && rmc_parsers[num_tokens]){ + rmc_parsers[num_tokens](token); + } + break; + } - // Prepare for next token - num_tokens++; - offset = 0; -#ifdef DEBUG_GPS - Serial.print(c); -#endif - break; + // Prepare for next token + num_tokens++; + offset = 0; + #ifdef DEBUG_GPS + Serial.print(c); + #endif + break; - default: - // Any other character - if (at_checksum) { - // Checksum value - their_checksum = their_checksum * 16 + from_hex(c); - } else { - // Regular NMEA data - if (offset < 15) { // Avoid buffer overrun (tokens can't be > 15 chars) - token[offset] = c; - offset++; - our_checksum ^= c; - } - } -#ifdef DEBUG_GPS - Serial.print(c); -#endif - } - return ret; + default: + // Any other character + if (at_checksum) { + // Checksum value + their_checksum = their_checksum * 16 + from_hex(c); + } else { + // Regular NMEA data + if (offset < 15) { // Avoid buffer overrun (tokens can't be > 15 chars) + token[offset] = c; + offset++; + our_checksum ^= c; + } + } + #ifdef DEBUG_GPS + Serial.print(c); + #endif + } + return ret; } diff --git a/master/master/lib/trackuinoGPS/gps.cpp b/master/master/lib/trackuinoGPS/gps.cpp --- a/master/master/lib/trackuinoGPS/gps.cpp +++ b/master/master/lib/trackuinoGPS/gps.cpp @@ -15,6 +15,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/*<--delete this + #include "config.h" #include "gps.h" #include @@ -117,6 +119,7 @@ float gps_speed = 0; float gps_altitude = 0; // Module functions +/// converts from hex to binary ?? unsigned char from_hex(char a) { if (a >= 'A' && a <= 'F') @@ -129,6 +132,7 @@ unsigned char from_hex(char a) return 0; } +/// determines what type of message is being sent ?? void parse_sentence_type(const char *token) { if (strcmp(token, "$GPGGA") == 0) { diff --git a/master/master/master.cproj b/master/master/master.cproj --- a/master/master/master.cproj +++ b/master/master/master.cproj @@ -192,13 +192,28 @@ compile + + compile + + + compile + + + compile + compile + + + + compile + + \ No newline at end of file