interface to GPS parser More...
#include <stdint.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <string.h>
#include <usarts.h>
#include <ff.h>
Go to the source code of this file.
Data Structures | |
struct | gps_time_s |
store GPS timestamp (time of day) More... | |
struct | gps_date_s |
store GPS date (day) More... | |
struct | gps_dms_s |
store one dimension of coordinate (degrees/minutes/seconds) More... | |
struct | gps_dop_s |
store "dilution of precision" More... | |
struct | gps_height_s |
store height info More... | |
struct | gps_sat_s |
store data for one satellite More... | |
struct | gps_position_t |
store all GPS data used for GPX logging More... | |
struct | gps_proto_functions_s |
function pointers to protocol-specific parser More... | |
struct | gps_proto_parser_s |
protocol-specific parser interface More... | |
struct | gps_parser_s |
internal state of parser More... | |
Defines | |
#define | GPS_DEGREE_SCALE (10000000L) |
#define | GPS_DEGREE_SCALE_EXP (7) |
#define | MAX_NUM_SATS (18) |
maximum number of satellites to allocate in data | |
#define | PROTO_CALL(FUNCP, ARGS...) |
call a protocol-specific function | |
Typedefs | |
typedef struct gps_time_s | gps_time_t |
store GPS timestamp (time of day) | |
typedef struct gps_date_s | gps_date_t |
store GPS date (day) | |
typedef int32_t | gps_degree_t |
store one dimension of coordinate | |
typedef struct gps_dms_s | gps_dms_t |
store one dimension of coordinate (degrees/minutes/seconds) | |
typedef struct gps_dop_s | gps_dop_t |
store "dilution of precision" | |
typedef struct gps_height_s | gps_height_t |
store height info | |
typedef struct gps_sat_s | gps_sat_t |
store data for one satellite | |
typedef struct gps_parser_s | gps_parser_t |
typedef struct gps_proto_functions_s | gps_proto_functions_t |
function pointers to protocol-specific parser | |
typedef struct gps_proto_parser_s | gps_proto_parser_t |
protocol-specific parser interface | |
Enumerations | |
enum | gps_line_status_t { GPS_LINE_MORE = 0, GPS_LINE_CKERR, GPS_LINE_OVERFLOW, GPS_LINE_OK, GPS_LINE_FIX, GPS_LINE_TIME, GPS_LINE_SAT } |
return status for gps_recvd() More... | |
enum | gps_proto_t { GPSPROTO_NONE = 0, GPSPROTO_NMEA, GPSPROTO_SiRF, GPSPROTO_NUMPROTOS } |
GPS data formats. | |
Functions | |
gps_dms_t | gps_degree_to_dms (gps_degree_t v) |
convert gps_degree_t into sign/degrees/minutes/Seconds | |
gps_parser_t * | new_gps_parser (usart_control_t *usart) |
create a new GPS parser instance | |
void | free_gps_parser (gps_parser_t *parser) |
free a GPS parser instance | |
gps_proto_t | gps_get_proto (gps_parser_t *parser) |
get currently used GPS protocol | |
gps_proto_t | gps_set_proto (gps_parser_t *parser, gps_proto_t newproto, baudrate_t baud) |
switch to another GPS protocol | |
void | gps_timestamp_set_trigger (gps_parser_t *parser, uint8_t trigger) |
set the trigger byte for timestamping | |
void | gps_timestamp_start_of_message (gps_parser_t *parser) |
mark start of message | |
baudrate_t | gps_set_baudrate (gps_parser_t *parser, baudrate_t baudrate) |
set baudrate of USART | |
void | gps_start_log (gps_parser_t *parser) |
start logging of raw GPS data | |
gps_line_status_t | gps_recvd (gps_parser_t *parser, usart_rxdata_t c) |
give one character to GPS parser | |
uint8_t | gps_usart_can_recv (gps_parser_t *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 | |
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() | |
uint8_t | gps_get_source (gps_parser_t *parser, const char **psrc, const char **pproto, baudrate_t *baud) |
get source parameter | |
uint8_t | gps_usart_is_active (gps_parser_t *parser) |
tell whether USART is active | |
void | gps_usart_power (gps_parser_t *parser, uint8_t onoff) |
set power status for USART used by that parser | |
void | gps_set_parsed_time (gps_parser_t *parser, gps_date_t date, gps_time_t time) |
provide parsed time to generic GPS layer | |
Variables | |
const gps_proto_functions_t | gps_proto_sirf |
const gps_proto_functions_t | gps_proto_nmea |
interface to GPS parser
#define PROTO_CALL | ( | FUNCP, | ||
ARGS... | ||||
) |
__extension__({ \ __typeof__(*FUNCP) __p = (__typeof__(*FUNCP))pgm_read_word (FUNCP); \ (__p) (ARGS); \ })
call a protocol-specific function
typedef int32_t gps_degree_t |
store one dimension of coordinate
The data is stored as . Positive value means North/East, negative means South/West.
enum gps_line_status_t |
return status for gps_recvd()
{ GPS_LINE_MORE = 0, GPS_LINE_CKERR, GPS_LINE_OVERFLOW, GPS_LINE_OK, GPS_LINE_FIX, GPS_LINE_TIME, GPS_LINE_SAT, } gps_line_status_t;
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_set_trigger | ( | gps_parser_t * | parser, | |
uint8_t | trigger | |||
) | [inline] |
set the trigger byte for timestamping
gps_timestamp_set_trigger() is intended to be called from the protocol-specific module to set the byte which triggers timestamping.
{ usart_timestamp_set_trigger (parser->usart, trigger); }
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; }