/* * Copyright © 2014 Kosma Moczek * This program is free software. It comes without any warranty, to the extent * permitted by applicable law. You can redistribute it and/or modify it under * the terms of the Do What The Fuck You Want To Public License, Version 2, as * published by Sam Hocevar. See the COPYING file for more details. */ #ifndef MINMEA_H #define MINMEA_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #ifdef MINMEA_INCLUDE_COMPAT #include #endif #ifndef MINMEA_MAX_SENTENCE_LENGTH #define MINMEA_MAX_SENTENCE_LENGTH 80 #endif #define FRAME_TXT_MAX_LEN (79) enum minmea_sentence_id { MINMEA_INVALID = -1, MINMEA_UNKNOWN = 0, MINMEA_SENTENCE_GBS, MINMEA_SENTENCE_GGA, MINMEA_SENTENCE_GLL, MINMEA_SENTENCE_GSA, MINMEA_SENTENCE_GST, MINMEA_SENTENCE_GSV, MINMEA_SENTENCE_RMC, MINMEA_SENTENCE_VTG, MINMEA_SENTENCE_ZDA, MINMEA_SENTENCE_TXT, MINMEA_SENTENCE_MAX_ID }; struct minmea_float { int_least32_t value; int_least32_t scale; }; struct minmea_date { int day; int month; int year; }; struct minmea_time { int hours; int minutes; int seconds; int microseconds; }; struct minmea_sentence_gbs { struct minmea_time time; struct minmea_float err_latitude; struct minmea_float err_longitude; struct minmea_float err_altitude; int svid; struct minmea_float prob; struct minmea_float bias; struct minmea_float stddev; }; struct minmea_sentence_rmc { struct minmea_time time; bool valid; struct minmea_float latitude; struct minmea_float longitude; struct minmea_float speed; struct minmea_float course; struct minmea_date date; struct minmea_float variation; }; struct minmea_sentence_gga { struct minmea_time time; struct minmea_float latitude; struct minmea_float longitude; int fix_quality; int satellites_tracked; struct minmea_float hdop; struct minmea_float altitude; char altitude_units; struct minmea_float height; char height_units; struct minmea_float dgps_age; }; enum minmea_gll_status { MINMEA_GLL_STATUS_DATA_VALID = 'A', MINMEA_GLL_STATUS_DATA_NOT_VALID = 'V', }; // FAA mode added to some fields in NMEA 2.3. enum minmea_faa_mode { MINMEA_FAA_MODE_AUTONOMOUS = 'A', MINMEA_FAA_MODE_DIFFERENTIAL = 'D', MINMEA_FAA_MODE_ESTIMATED = 'E', MINMEA_FAA_MODE_MANUAL = 'M', MINMEA_FAA_MODE_SIMULATED = 'S', MINMEA_FAA_MODE_NOT_VALID = 'N', MINMEA_FAA_MODE_PRECISE = 'P', }; struct minmea_sentence_gll { struct minmea_float latitude; struct minmea_float longitude; struct minmea_time time; char status; char mode; }; struct minmea_sentence_gst { struct minmea_time time; struct minmea_float rms_deviation; struct minmea_float semi_major_deviation; struct minmea_float semi_minor_deviation; struct minmea_float semi_major_orientation; struct minmea_float latitude_error_deviation; struct minmea_float longitude_error_deviation; struct minmea_float altitude_error_deviation; }; enum minmea_gsa_mode { MINMEA_GPGSA_MODE_AUTO = 'A', MINMEA_GPGSA_MODE_FORCED = 'M', }; enum minmea_gsa_fix_type { MINMEA_GPGSA_FIX_NONE = 1, MINMEA_GPGSA_FIX_2D = 2, MINMEA_GPGSA_FIX_3D = 3, }; struct minmea_sentence_gsa { char mode; int fix_type; int sats[12]; struct minmea_float pdop; struct minmea_float hdop; struct minmea_float vdop; int sysid; }; struct minmea_sat_info { int nr; int elevation; int azimuth; int snr; }; struct minmea_sentence_gsv { int total_msgs; int msg_nr; int total_sats; struct minmea_sat_info sats[4]; }; struct minmea_sentence_vtg { struct minmea_float true_track_degrees; struct minmea_float magnetic_track_degrees; struct minmea_float speed_knots; struct minmea_float speed_kph; enum minmea_faa_mode faa_mode; }; struct minmea_sentence_zda { struct minmea_time time; struct minmea_date date; int hour_offset; int minute_offset; }; struct minmea_sentence_txt { int count; int index; char txt[FRAME_TXT_MAX_LEN + 1]; }; /** * Calculate raw sentence checksum. Does not check sentence integrity. */ uint8_t minmea_checksum(const char *sentence); /** * Check sentence validity and checksum. Returns true for valid sentences. */ bool minmea_check(const char *sentence, bool strict); /** * Determine talker identifier. */ bool minmea_talker_id(char talker[3], const char *sentence); /** * Determine sentence identifier. */ enum minmea_sentence_id minmea_sentence_id(const char *sentence, bool strict); /** * Scanf-like processor for NMEA sentences. Supports the following formats: * c - single character (char *) * d - direction, returned as 1/-1, default 0 (int *) * f - fractional, returned as value + scale (struct minmea_float *) * i - decimal, default zero (int *) * s - string (char *) * t - talker identifier and type (char *) * D - date (struct minmea_date *) * T - time stamp (struct minmea_time *) * _ - ignore this field * ; - following fields are optional * Returns true on success. See library source code for details. */ bool minmea_scan(const char *sentence, const char *format, ...); /* * Parse a specific type of sentence. Return true on success. */ bool minmea_parse_gbs(struct minmea_sentence_gbs *frame, const char *sentence); bool minmea_parse_rmc(struct minmea_sentence_rmc *frame, const char *sentence); bool minmea_parse_gga(struct minmea_sentence_gga *frame, const char *sentence); bool minmea_parse_gsa(struct minmea_sentence_gsa *frame, const char *sentence); bool minmea_parse_gll(struct minmea_sentence_gll *frame, const char *sentence); bool minmea_parse_gst(struct minmea_sentence_gst *frame, const char *sentence); bool minmea_parse_gsv(struct minmea_sentence_gsv *frame, const char *sentence); bool minmea_parse_vtg(struct minmea_sentence_vtg *frame, const char *sentence); bool minmea_parse_zda(struct minmea_sentence_zda *frame, const char *sentence); bool minmea_parse_txt(struct minmea_sentence_txt *frame, const char *sentence); /** * Convert GPS UTC date/time representation to a UNIX calendar time. */ int minmea_getdatetime(struct tm *tm, const struct minmea_date *date, const struct minmea_time *time_); /** * Convert GPS UTC date/time representation to a UNIX timestamp. */ int minmea_gettime(struct timespec *ts, const struct minmea_date *date, const struct minmea_time *time_); /** * Rescale a fixed-point value to a different scale. Rounds towards zero. */ static inline int_least32_t minmea_rescale(const struct minmea_float *f, int_least32_t new_scale) { if (f->scale == 0) return 0; if (f->scale == new_scale) return f->value; if (f->scale > new_scale) return (f->value + ((f->value > 0) - (f->value < 0)) * f->scale/new_scale/2) / (f->scale/new_scale); else return f->value * (new_scale/f->scale); } /** * Convert a fixed-point value to a floating-point value. * Returns NaN for "unknown" values. */ static inline float minmea_tofloat(const struct minmea_float *f) { if (f->scale == 0) return 0; return (float) f->value / (float) f->scale; } /** * Convert a raw coordinate to a floating point DD.DDD... value. * Returns NaN for "unknown" values. */ static inline float minmea_tocoord(const struct minmea_float *f) { if (f->scale == 0) return 0; if (f->scale > (INT_LEAST32_MAX / 100)) return 0; if (f->scale < (INT_LEAST32_MIN / 100)) return 0; int_least32_t degrees = f->value / (f->scale * 100); int_least32_t minutes = f->value % (f->scale * 100); return (float) degrees + (float) minutes / (60 * f->scale); } /** * Convert a raw coordinate to a floating point DD.DDD... value. * Returns NaN for "unknown" values. */ static inline uint32_t minmea_tocoord2(const struct minmea_float *f) { if (f->scale == 0) return 0; if (f->scale > (INT_LEAST32_MAX / 100)) return 0; if (f->scale < (INT_LEAST32_MIN / 100)) return 0; int_least32_t degrees = f->value / (f->scale * 100); int_least32_t minutes = f->value % (f->scale * 100); uint32_t ret = degrees * 10000000 + (uint32_t)(((float) minutes / (60 * f->scale)) * 10000000); return ret; } /** * Check whether a character belongs to the set of characters allowed in a * sentence data field. */ static inline bool minmea_isfield(char c) { return isprint((unsigned char) c) && c != ',' && c != '*'; } // 扩展 #define RECV_BUFF_SIZE (2048) #define FRAME_GSA_MAX (7) #define FRAME_GSV_MAX (24) #define FRAME_TXT_MAX (80) #define LUAT_LIBGNSS_MAX_LINE (128) int luat_libgnss_init(int clear); int luat_libgnss_parse_data(const char* data, size_t len); int luat_libgnss_parse_nmea(const char* line); void luat_libgnss_uart_recv_cb(int uart_id, uint32_t data_len); int luat_libgnss_state_onchanged(int state); int luat_libgnss_on_rawdata(const char* data, size_t len, int type); enum GNSS_STATE { GNSS_STATE_INIT = 0, GNSS_STATE_FIXED, GNSS_STATE_LOSE, GNSS_STATE_OPEN, GNSS_STATE_CLOSE }; // typedef union // { // struct minmea_sentence_rmc frame_rmc; // struct minmea_sentence_gga frame_gga; // struct minmea_sentence_gll frame_gll; // struct minmea_sentence_gst frame_gst; // struct minmea_sentence_gsv frame_gsv; // struct minmea_sentence_vtg frame_vtg; // struct minmea_sentence_gsa frame_gsa; // struct minmea_sentence_zda frame_zda; // struct minmea_sentence_txt txt; // }minmea_data_t; typedef struct minmea_data { char data[LUAT_LIBGNSS_MAX_LINE]; uint64_t tm; }minmea_data_t; typedef struct luat_libgnss { uint32_t fix_at_ticks; struct minmea_sentence_rmc frame_rmc; minmea_data_t* rmc; minmea_data_t *gga; minmea_data_t *gll; minmea_data_t *gst; minmea_data_t *vtg; minmea_data_t *zda; minmea_data_t *gsv[FRAME_GSV_MAX]; minmea_data_t *gsa[FRAME_GSA_MAX]; minmea_data_t* txt; uint8_t debug; uint8_t rtc_auto; uint8_t gsa_offset; } luat_libgnss_t; int luat_libgnss_data_check(minmea_data_t* data, uint32_t timeout, uint64_t tnow); #ifdef __cplusplus } #endif #endif /* MINMEA_H */ /* vim: set ts=4 sw=4 et: */