interface to GPS parser More...
#include <stdlib.h>#include <stdio.h>#include <avr/pgmspace.h>#include "gps-parser.h"#include "nmea_hl.h"#include "sirf3.h"#include <rtc.h>#include <clock.h>Functions | |
| void | gps_start_log (gps_parser_t *parser) |
| start logging of raw GPS data | |
| gps_parser_t * | new_gps_parser (usart_control_t *usart) |
| create a new GPS parser instance | |
| gps_proto_t | gps_set_proto (gps_parser_t *parser, gps_proto_t newproto, baudrate_t baud) |
| switch to another GPS protocol | |
| baudrate_t | gps_set_baudrate (gps_parser_t *parser, baudrate_t baudrate) |
| set baudrate of USART | |
| void | gps_timestamp_start_of_message (gps_parser_t *parser) |
| mark start of message | |
| void | gps_set_parsed_time (gps_parser_t *parser, gps_date_t date, gps_time_t time) |
| provide parsed time to generic GPS layer | |
| baudrate_t | gps_change_baudrate (gps_parser_t *parser, int8_t incdec) |
| gps_line_status_t | gps_recvd (gps_parser_t *parser, usart_rxdata_t c) |
| give one character to GPS parser | |
| gps_line_status_t | gps_usart_recv_and_handle (gps_parser_t *parser, usart_rxdata_t *c) |
| get one character from USART and give that to GPS parser | |
| gps_dms_t | gps_degree_to_dms (gps_degree_t v) |
| convert gps_degree_t into sign/degrees/minutes/Seconds | |
| int | gps_format_position (char *buf, size_t sz, gps_parser_t *parser) |
| format current position for output | |
| gps_sat_t * | gps_get_satellite (gps_parser_t *parser, uint8_t idx) |
| return reception status for one satellite | |
| uint8_t | gps_get_time (gps_parser_t *parser, gps_date_t *pdate, gps_time_t *ptime) |
| get current time | |
| uint8_t | gps_get_position (gps_parser_t *parser, gps_degree_t *plat, gps_degree_t *plon) |
| get current position | |
| uint8_t | gps_get_height (gps_parser_t *parser, gps_height_t *pheight) |
| get height above WGS84 ellipsoid | |
| uint8_t | gps_get_hdop (gps_parser_t *parser, gps_dop_t *phdop) |
| uint8_t | gps_get_data (gps_parser_t *parser, gps_position_t *data) |
| get current GPS data, to be passed to hlog_record() | |
Variables | |
| const gps_proto_functions_t *const proto_list[GPSPROTO_NUMPROTOS] | PROGMEM |
| const char * | gps_proto_names [GPSPROTO_NUMPROTOS] |
interface to GPS parser
| uint8_t gps_get_data | ( | gps_parser_t * | parser, | |
| gps_position_t * | data | |||
| ) |
get current GPS data, to be passed to hlog_record()
| parser | ||
| data | pointer to store GPS data |
{
int res = 0;
res = gps_get_time (parser, &data->date, &data->time);
gps_get_position (parser, &data->lat, &data->lon);
gps_get_height (parser, &data->height);
gps_get_hdop (parser, &data->hdop);
return res;
}
| uint8_t gps_get_height | ( | gps_parser_t * | parser, | |
| gps_height_t * | pheight | |||
| ) |
get height above WGS84 ellipsoid
| parser | ||
| pheight | pointer to store height into |
{
*pheight = parser->height;
return 1;
}
| uint8_t gps_get_position | ( | gps_parser_t * | parser, | |
| gps_degree_t * | plat, | |||
| gps_degree_t * | plon | |||
| ) |
| gps_sat_t* gps_get_satellite | ( | gps_parser_t * | parser, | |
| uint8_t | idx | |||
| ) |
return reception status for one satellite
| parser | ||
| idx | index of satellite to get status for |
{
gps_parser_t * p = parser;
if (idx < sizeof(p->satellites)/sizeof(p->satellites[0])
&& idx < p->num_sats)
return &p->satellites[idx];
else
return NULL;
}
| uint8_t gps_get_time | ( | gps_parser_t * | parser, | |
| gps_date_t * | pdate, | |||
| gps_time_t * | ptime | |||
| ) |
get current time
| parser | ||
| pdate | pointer to place date into, if not NULL | |
| ptime | pointer to place time into, if not NULL |
{
gps_parser_t * p = parser;
if (!p->date.month)
return 0;
if (pdate) *pdate = p->date;
if (ptime) *ptime = p->time;
return 1;
}
| gps_line_status_t gps_recvd | ( | gps_parser_t * | parser, | |
| usart_rxdata_t | c | |||
| ) |
give one character to GPS parser
{
if (c.flags) {
/* Trigger baud rate detection */
if (c.flags & USART_FRAME_ERROR) {
uint16_t d = c.data;
uint8_t i;
uint8_t faster = 0;
parser->autobaud.frame_errors++;
/* add start and stop bits */
d |= 0xFF00;
d <<= 1;
for (i = 7; i; i--) {
if ((d & 0x07) == 0x02 || (d & 0x07) == 0x05) {
faster = ++parser->autobaud.faster;
break;
}
d >>= 1;
}
if (faster >= 20
/* prevent overflow */
&& parser->autobaud.baud*2
<= pgm_read_dword (&parser->proto_parser->func->baudrate_max)) {
baudrate_t old = parser->autobaud.baud;
gps_change_baudrate (parser, +1);
printf_P (PSTR("AUTOBAUD(%lu=>%lu)\r\n"), old, parser->autobaud.baud);
return GPS_LINE_CKERR;
}
/* slow down ? */
d = c.data;
d |= 0xFF00;
d <<= 1;
d ^= d >> 1;
d &= 0x55;
if (d == 0) {
parser->autobaud.slower++;
if (parser->autobaud.slower >= 40
&& parser->autobaud.baud > 1200 /* limit */) {
baudrate_t old = parser->autobaud.baud;
gps_change_baudrate (parser, -1);
printf_P (PSTR("AUTOBAUD(%lu=>%lu)\r\n"), old, parser->autobaud.baud);
return GPS_LINE_CKERR;
}
}
}
/* save timestamp-related data */
if (c.flags & USART_TIMESTAMPED) {
parser->msg_timestamp[0].tcnt2 = usart_get_timestamp (parser->usart);
}
}
return PROTO_CALL(&(parser->proto_parser->func->recvd), parser, c);
}
| void gps_set_parsed_time | ( | gps_parser_t * | parser, | |
| gps_date_t | date, | |||
| gps_time_t | time | |||
| ) |
provide parsed time to generic GPS layer
gps_set_parsed_time() is intended to be called from the protocol-specific module to provide the time parsed from a GPS message.
If the time has changed compared to the time already stored in *parser, this function adjusts the internal clock assuming the current message is the first message in the dataset.
{
gps_parser_t *p = parser;
uint8_t changed = 0;
#ifdef DEBUG
printf_P (PSTR("TIME %04u-%02u-%02u %02u:%02u:%05u\r\n"),
date.year ? date.year : p->date.year, date.month, date.day,
time.hour, time.min, time.msec);
#endif
if (date.year) {
if (date.year < 100 && p->date.year > 100) {
date.year = date.year + ((p->date.year/100)*100);
}
}
if (date.year && date.month && date.day) {
changed = p->date.year != date.year || p->date.month != date.month
|| p->date.day != date.day;
if (changed) p->date = date;
}
if (changed || p->time.hour >= time.hour || p->time.min >= time.min
|| p->time.msec >= time.msec) {
changed |= 1;
p->time = time;
}
if (changed) {
clock_time_t clktime =
{
.year = date.year, .month = date.month, .day = date.day,
.hour = time.hour, .min = time.min, .sec = time.msec/1000,
};
if (date.year == 0)
clktime.year = p->date.year;
if (date.month == 0)
clktime.month = p->date.month;
if (date.day == 0)
clktime.day = p->date.day;
/* call clock adjustment */
clock_adjust (p->msg_timestamp_ticks, p->msg_timestamp[1].tcnt2,
strcmp_P (p->usart_name, PSTR("USART3"))
? CLOCKADJ_GPS_MOD : CLOCKADJ_GPS_EXT,
&clktime);
}
}
| gps_proto_t gps_set_proto | ( | gps_parser_t * | parser, | |
| gps_proto_t | newproto, | |||
| baudrate_t | baud | |||
| ) |
switch to another GPS protocol
Switch to another GPS protocol if it is obvious how to do that. This function does not try to figure out a way for the switch in the case a switch to an intermediate protocol is needed.
| parser | instance of parser to switch protocol for | |
| newproto | requested protocol | |
| baud | requested new baud rate |
{
const gps_proto_functions_t * f1 = parser->proto_parser->func;
__typeof__ (f1->switchproto) sw
= (__typeof__(f1->switchproto)) pgm_read_word (&f1->switchproto);
if (sw) {
const gps_proto_functions_t * f = (sw) (parser, newproto, baud);
if (f && f != f1) {
PROTO_CALL(&parser->proto_parser->func->freeparser, parser);
parser->proto_parser = PROTO_CALL(&f->newparser, parser);
}
}
return gps_get_proto (parser);
}
| void gps_start_log | ( | gps_parser_t * | parser | ) |
start logging of raw GPS data
| parser |
{
gps_parser_t *p = parser;
FIL * logfile;
if (!p->usart_name) return;
logfile = malloc (sizeof(FIL));
if (logfile) {
XCHAR fname[16];
FRESULT r;
strcpy (fname, p->usart_name);
strcat_P (fname, PSTR(".log\0"));
printf_P (PSTR("f_open(%s)\r\n"), fname);
r = f_open (logfile, fname, FA_WRITE | FA_OPEN_ALWAYS);
if (r == FR_OK) {
/* seek to end for append */
r = f_lseek (logfile, logfile->fsize);
if (r != FR_OK) {
printf_P (PSTR("f_lseek(%s,%lu) failed: %d\r\n"),
fname, logfile->fsize, r);
f_close (logfile);
goto free_file;
}
p->logfile = logfile;
} else {
printf_P (PSTR("f_open(%s) failed: %d\r\n"), fname, r);
free_file:
free (logfile);
}
}
}
| void gps_timestamp_start_of_message | ( | gps_parser_t * | parser | ) | [inline] |
mark start of message
gps_timestamp_start_of_message() should be called by the protocol-specific module when its state machine thinks a message has started
{
parser->msg_timestamp[1] = parser->msg_timestamp[0];
parser->msg_timestamp_ticks = hl_get_current_time().ticks;
}
| gps_parser_t* new_gps_parser | ( | usart_control_t * | usart | ) |
create a new GPS parser instance
| usart | USART structure to be used for control messages |
{
gps_parser_t * p = malloc (sizeof (*p));
uint8_t i;
p->usart = usart;
p->date.year = 2000;
p->date.month = 0;
p->date.day = 0;
p->num_sats = 0;
for (i=0; i < MAX_NUM_SATS; i++)
p->satellites[i].snr = 0xFF;
gps_init_autobaud (p, 2400);
p->usart_name = malloc (strlen_P(usart->name)+1);
if (p->usart_name)
strcpy_P (p->usart_name, usart->name);
p->logfile = NULL;
p->proto_parser = PROTO_CALL(&gps_proto_nmea.newparser, p);
return p;
}
| const char* gps_proto_names[GPSPROTO_NUMPROTOS] |
{
[GPSPROTO_NONE] = "",
[GPSPROTO_NMEA] = "NMEA",
[GPSPROTO_SiRF] = "SiRF",
}
| const gps_proto_functions_t* const proto_list [GPSPROTO_NUMPROTOS] PROGMEM |
{
[GPSPROTO_NONE] = NULL,
[GPSPROTO_NMEA] = &gps_proto_nmea,
[GPSPROTO_SiRF] = &gps_proto_sirf,
}
1.7.1