diff --git a/README.md b/README.md index c8908d8..2307946 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ systems. * ``RMC`` (Recommended Minimum: position, velocity, time) * ``GGA`` (Fix Data) * ``GSA`` (DOP and active satellites) +* ``GLL`` (Geographic Position -- Latitude/Longitude) * ``GST`` (Pseudorange Noise Statistics) * ``GSV`` (Satellites in view) diff --git a/minmea.c b/minmea.c index 584880c..f14290b 100644 --- a/minmea.c +++ b/minmea.c @@ -333,6 +333,8 @@ enum minmea_sentence_id minmea_sentence_id(const char *sentence) return MINMEA_SENTENCE_GGA; if (!strcmp(type+2, "GSA")) return MINMEA_SENTENCE_GSA; + if (!strcmp(type+2, "GLL")) + return MINMEA_SENTENCE_GLL; if (!strcmp(type+2, "GST")) return MINMEA_SENTENCE_GST; if (!strcmp(type+2, "GSV")) @@ -430,6 +432,30 @@ bool minmea_parse_gsa(struct minmea_sentence_gsa *frame, const char *sentence) return true; } +bool minmea_parse_gll(struct minmea_sentence_gll *frame, const char *sentence) +{ + // $GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41$; + char type[6]; + int latitude_direction; + int longitude_direction; + + if (!minmea_scan(sentence, "tfdfdTc;c", + type, + &frame->latitude, &latitude_direction, + &frame->longitude, &longitude_direction, + &frame->time, + &frame->status, + &frame->mode)) + return false; + if (strcmp(type+2, "GLL")) + return false; + + frame->latitude.value *= latitude_direction; + frame->longitude.value *= longitude_direction; + + return true; +} + bool minmea_parse_gst(struct minmea_sentence_gst *frame, const char *sentence) { // $GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58 diff --git a/minmea.h b/minmea.h index 65fe7e9..30b0b86 100644 --- a/minmea.h +++ b/minmea.h @@ -31,6 +31,7 @@ enum minmea_sentence_id { MINMEA_SENTENCE_RMC, MINMEA_SENTENCE_GGA, MINMEA_SENTENCE_GSA, + MINMEA_SENTENCE_GLL, MINMEA_SENTENCE_GST, MINMEA_SENTENCE_GSV, }; @@ -76,6 +77,25 @@ struct minmea_sentence_gga { int dgps_age; }; +enum minmea_gll_status { + MINMEA_GLL_STATUS_DATA_VALID = 'A', + MINMEA_GLL_STATUS_DATA_NOT_VALID = 'V', +}; + +enum minmea_gll_mode { + MINMEA_GLL_MODE_AUTONOMOUS = 'A', + MINMEA_GLL_MODE_DPGS = 'D', + MINMEA_GLL_MODE_DR = 'E', +}; + +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; @@ -155,6 +175,7 @@ bool minmea_scan(const char *sentence, const char *format, ...); 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); diff --git a/tests.c b/tests.c index 6ee4228..5edc737 100644 --- a/tests.c +++ b/tests.c @@ -519,6 +519,42 @@ START_TEST(test_minmea_parse_gsa1) } END_TEST +START_TEST(test_minmea_parse_gll1) +{ + const char *sentence = "$GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41"; + struct minmea_sentence_gll frame = {}; + struct minmea_sentence_gll expected = { + .latitude = { 37232475, 10000 }, + .longitude = { -121583416, 10000 }, + .time = { 16, 12, 29, 487000 }, + .status = MINMEA_GLL_STATUS_DATA_VALID, + .mode = MINMEA_GLL_MODE_AUTONOMOUS, + }; + + ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_parse_gll(&frame, sentence) == true); + ck_assert(!memcmp(&frame, &expected, sizeof(frame))); +} +END_TEST + +START_TEST(test_minmea_parse_gll2) +{ + const char *sentence = "$GPGLL,4916.45,N,12311.12,W,225444,A"; + struct minmea_sentence_gll frame = {}; + struct minmea_sentence_gll expected = { + .latitude = { 491645, 100 }, + .longitude = { -1231112, 100 }, + .time = { 22, 54, 44 }, + .status = MINMEA_GLL_STATUS_DATA_VALID, + .mode = 0, + }; + + ck_assert(minmea_check(sentence) == true); + ck_assert(minmea_parse_gll(&frame, sentence) == true); + ck_assert(!memcmp(&frame, &expected, sizeof(frame))); +} +END_TEST + START_TEST(test_minmea_parse_gsv1) { const char *sentence = "$GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D"; @@ -566,6 +602,7 @@ START_TEST(test_minmea_usage1) "$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62", "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47", "$GNGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1", + "$GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41", "$GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58", NULL, }; @@ -587,6 +624,11 @@ START_TEST(test_minmea_usage1) ck_assert(minmea_parse_gsa(&frame, *sentence) == true); } break; + case MINMEA_SENTENCE_GLL: { + struct minmea_sentence_gll frame; + ck_assert(minmea_parse_gll(&frame, *sentence) == true); + } break; + case MINMEA_SENTENCE_GST: { struct minmea_sentence_gst frame; ck_assert(minmea_parse_gst(&frame, *sentence) == true); @@ -692,6 +734,8 @@ Suite *minmea_suite(void) tcase_add_test(tc_parse, test_minmea_parse_rmc2); tcase_add_test(tc_parse, test_minmea_parse_gga1); tcase_add_test(tc_parse, test_minmea_parse_gsa1); + tcase_add_test(tc_parse, test_minmea_parse_gll1); + tcase_add_test(tc_parse, test_minmea_parse_gll2); tcase_add_test(tc_parse, test_minmea_parse_gst1); tcase_add_test(tc_parse, test_minmea_parse_gsv1); suite_add_tcase(s, tc_parse);