spiralray gps decoder
Dependents: SakuraIO_Evaluation_Board_Standard SakuraIO_Evalution_Board_Standard sakuraio_plus_rental_server
gps.cpp
- Committer:
- misodengaku
- Date:
- 2019-01-15
- Revision:
- 4:82d2fced184b
- Parent:
- 2:fc3ce3241d89
File content as of revision 4:82d2fced184b:
#include "gps.h"
void GPSDecoder::set_nmea_message(char *nmea_msg)
{
strcpy(nmea_line, nmea_msg);
}
void GPSDecoder::decode()
{
char *nmea_lines[MAXTOKEN];
//printf("%s\r\n", nmea_msg);
if (validate() != 0) {
printf("invalid message\n");
return;
}
uint8_t nmea_line_index = split(nmea_line, ',', nmea_lines, MAXTOKEN);
#if 0
for (int i = 0; i < nmea_line_index; i++) {
printf("[%2d]%s\r\n", i, nmea_lines[i]);
}
#endif
if (strcmp((nmea_lines[0]) + 3, "RMC") == 0) {
double decimal_part[2] = {0};
/* 時刻のデコード */
hour = (uint8_t)str2int(nmea_lines[1], 2);
min = (uint8_t)str2int(nmea_lines[1] + 2, 2);
sec = (uint8_t)str2int(nmea_lines[1] + 4, 2);
msec = (uint16_t)str2int(nmea_lines[1] + 7, 3);
/* 日付のデコード */
day = (uint8_t)str2int(nmea_lines[9], 2);
month = (uint8_t)str2int(nmea_lines[9] + 2, 2);
year = (uint16_t)str2int(nmea_lines[9] + 4, 2) + 2000;
if (nmea_lines[2][0] == 'A') {
//printf("RMC mode: Information\r\n");
} else if (nmea_lines[2][0] == 'V') {
//printf("RMC mode: Warning\r\n");
} else {
printf("RMC mode: invalid");
return;
}
if (nmea_lines[2][0] == 'A') {
if (nmea_lines[2][0] == 'A') {
/* 位置情報のデコード */
decimal_part[0] = modf(strtof(nmea_lines[3], NULL), &latitude); // 秒
latitude /= 100;
decimal_part[1] = floor((modf(latitude, &latitude) * 100) + 0.5); // 分
latitude += (decimal_part[1] + decimal_part[0]) / 60;
if (nmea_lines[4][0] == 'S')
latitude = -latitude;
decimal_part[0] = modf(strtof(nmea_lines[5], NULL), &longitude); // 秒
longitude /= 100;
decimal_part[1] = floor((modf(longitude, &longitude) * 100) + 0.5); // 分
longitude += (decimal_part[1] + decimal_part[0]) / 60;
if (nmea_lines[6][0] == 'W')
longitude = -longitude;
/* 移動速度のデコード */
speed = strtof(nmea_lines[7], NULL) * 1.852f; // knot to km/h
move_direction = strtof(nmea_lines[8], NULL);
}
} else {
longitude = 0;
latitude = 0;
}
} else if (strcmp((nmea_lines[0]) + 3, "GGA") == 0) {
double decimal_part[2] = {0};
/* 時刻のデコード */
hour = (uint8_t)str2int(nmea_lines[1], 2);
min = (uint8_t)str2int(nmea_lines[1] + 2, 2);
sec = (uint8_t)str2int(nmea_lines[1] + 4, 2);
msec = (uint16_t)str2int(nmea_lines[1] + 7, 3);
// GGAでは日付は不明
/* 位置情報のデコード */
decimal_part[0] = modf(strtof(nmea_lines[2], NULL), &latitude); // 秒
latitude /= 100;
decimal_part[1] = floor((modf(latitude, &latitude) * 100) + 0.5); // 分
latitude += (decimal_part[1] + decimal_part[0]) / 60;
if (nmea_lines[3][0] == 'S')
latitude = -latitude;
decimal_part[0] = modf(strtof(nmea_lines[4], NULL), &longitude); // 秒
longitude /= 100;
decimal_part[1] = floor((modf(longitude, &longitude) * 100) + 0.5); // 分
longitude += (decimal_part[1] + decimal_part[0]) / 60;
if (nmea_lines[5][0] == 'W')
longitude = -longitude;
// 移動速度と移動方向はGGAではわからない
}
}
// valid = 0
// invalid = other
uint8_t GPSDecoder::validate()
{
uint8_t checksum = 0, nmea_checksum, flag = 0;
char checksum_str[3] = {0};
if (nmea_line[0] != '$') {
// printf("invalid preamble %02X\n", nmea_line[0]);
return 1;
}
for (int i = 1; i < strlen((char *)nmea_line); i++) {
if (flag) {
// 2byte checksum
memcpy(checksum_str, (char *)nmea_line + i, 2);
nmea_checksum = (uint8_t)strtol(checksum_str, NULL, 16);
break;
} else {
if (nmea_line[i] == '*') {
flag = 1;
continue;
}
checksum = checksum ^ nmea_line[i];
}
}
if (checksum != nmea_checksum) {
// printf("invalid checksum\n");
return 2;
}
// printf("validation passed\n");
return 0;
}
long GPSDecoder::str2int(char *src_ptr, uint8_t len)
{
char tmp[16] = {0};
memcpy(tmp, src_ptr, len);
return strtol(tmp, NULL, 10);
}
int GPSDecoder::split(char *str, const char delim, char *token[], int max_item)
{
int cnt = 0;
int len = strlen(str);
token[cnt++] = str;
for (int i = 0; i < len; i++) {
if (str[i] == delim) {
str[i] = '\0';
if (cnt == max_item)
return cnt;
token[cnt++] = str + i + 1;
}
}
return cnt;
}
time_t GPSDecoder::get_unixtime()
{
struct tm t;
t.tm_sec = sec;
t.tm_min = min;
t.tm_hour = hour;
t.tm_mday = day;
t.tm_mon = month - 1;
t.tm_year = year - 1900;
return mktime(&t);
}
void GPSDecoder::dump_info(char *buf)
{
sprintf(buf, "%d/%02d/%02d %02d:%02d:%02d.%03d (UTC)\r\n", year, month, day, hour, min, sec, msec);
sprintf(buf, "%slatitude: %f\r\n", buf, latitude);
sprintf(buf, "%slongitude: %f\r\n", buf, longitude);
sprintf(buf, "%sspeed %f km/h (%f knot)\r\n", buf, speed, speed / 1.852f);
sprintf(buf, "%sdirection %f degree\r\n", buf, move_direction);
}
SAKURA Internet