Skip to content

Commit

Permalink
Merge branch 'pr/siriobalmelli-goss-pubx-time' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
MaJerle committed Apr 11, 2020
2 parents fbffc54 + bd8f227 commit 3595fb9
Show file tree
Hide file tree
Showing 10 changed files with 415 additions and 35 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,4 @@ log_file.txt
project.ioc
mx.scratch
*.tilen majerle
*.exe
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ Fresh contributions are always welcome. Simple instructions to proceed::
Alternatively you may:

1. Report a bug
2. Ask for a feature request
2. Ask for a feature request

## Test

To build the code and run basic tests on your host::

cd examples
make test
40 changes: 40 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# gps-nmea-parser examples and tests Makefile
# (c) 2020 Sirio, Balmelli Analog & Digital

TARGETS := \
example.exe \
example_stat.exe \
test_code.exe \
test_time.exe

.PHONY: all clean test
all: $(TARGETS)

clean:
@rm -fv $(TARGETS)

test: $(TARGETS)
@for tgt in $(TARGETS); do \
echo "\n--- $$tgt ---"; \
./$$tgt; \
done

CFLAGS += -Wall \
-DDEBUG=1 \
-I../gps_nmea_parser/src/include \
-I./

example.exe: example.c

example_stat.exe: CFLAGS += -DGPS_CFG_STATUS=1
example_stat.exe: example_stat.c

test_code.exe: ../gps_nmea_parser/src/gps/gps.c test_code.c ../dev/VisualStudio/main.c

test_time.exe: CFLAGS += \
-DGPS_CFG_STATEMENT_PUBX=1 \
-DGPS_CFG_STATEMENT_PUBX_TIME=1
test_time.exe: ../gps_nmea_parser/src/gps/gps.c test_time.c ../dev/VisualStudio/main.c

$(TARGETS) : ../gps_nmea_parser/src/gps/gps.c
$(CC) -o $@ $(CFLAGS) $^
2 changes: 1 addition & 1 deletion examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ gps_rx_data[] = ""

int
main() {
/* Init GPS */
/* Init GPS */
gps_init(&hgps);

/* Process all input data */
Expand Down
76 changes: 76 additions & 0 deletions examples/example_stat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* This example tests the callback functionality of gps_process()
* when the GPS_CFG_STATUS flag is set.
*/
#include "gps/gps.h"
#include <string.h>
#include <stdio.h>

#if ! GPS_CFG_STATUS
#error "this test must be compiled with -DGPS_CFG_STATUS=1"
#endif /* ! GPS_CFG_STATUS */

/* GPS handle */
gps_t hgps;

/**
* \brief Dummy data from GPS receiver
*/
const char
gps_rx_data[] = ""
"$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F\r\n"
"$GPRMB,A,,,,,,,,,,,,V*71\r\n"
"$GPGGA,183730,3907.356,N,12102.482,W,1,05,1.6,646.4,M,-24.1,M,,*75\r\n"
"$GPGSA,A,3,02,,,07,,09,24,26,,,,,1.6,1.6,1.0*3D\r\n"
"$GPGSV,2,1,08,02,43,088,38,04,42,145,00,05,11,291,00,07,60,043,35*71\r\n"
"$GPGSV,2,2,08,08,02,145,00,09,46,303,47,24,16,178,32,26,18,231,43*77\r\n"
"$PGRME,22.0,M,52.9,M,51.0,M*14\r\n"
"$GPGLL,3907.360,N,12102.481,W,183730,A*33\r\n"
"$PGRMZ,2062,f,3*2D\r\n"
"$PGRMM,WGS84*06\r\n"
"$GPBOD,,T,,M,,*47\r\n"
"$GPRTE,1,1,c,0*07\r\n"
"$GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67\r\n"
"$GPRMB,A,,,,,,,,,,,,V*71\r\n";

const gps_statement_t expected[] = {
STAT_RMC,
STAT_UNKNOWN,
STAT_GGA,
STAT_GSA,
STAT_GSV,
STAT_GSV,
STAT_UNKNOWN,
STAT_UNKNOWN,
STAT_UNKNOWN,
STAT_CHECKSUM_FAIL,
STAT_UNKNOWN,
STAT_UNKNOWN,
STAT_RMC,
STAT_UNKNOWN
};

static int err_cnt;

void callback(gps_statement_t res) {
static int i;

if (res != expected[i]) {
printf("failed i %d, expected res %d but received %d\n",
i, expected[i], res);
++err_cnt;
}

++i;
}

int
main() {
/* Init GPS */
gps_init(&hgps);

/* Process all input data */
gps_process(&hgps, gps_rx_data, strlen(gps_rx_data), callback);

return err_cnt;
}
12 changes: 1 addition & 11 deletions examples/test_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,7 @@
#include "gps/gps.h"
#include <string.h>
#include <stdio.h>
#include <math.h>

#define RUN_TEST(x) do { \
if ((x)) { \
printf("Test passed on line %u with condition " # x "\r\n", (unsigned)__LINE__);\
} else { \
printf("Test FAILED on line %u with condition " # x "\r\n", (unsigned)__LINE__ ); \
} \
} while (0)
#define FLT_IS_EQUAL(x, y) (fabs((double)(x) - (double)(y)) < 0.00001)
#define INT_IS_EQUAL(x, y) ((int)((x) == (y)))
#include "test_common.h"

/* GPS handle */
gps_t hgps;
Expand Down
18 changes: 18 additions & 0 deletions examples/test_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef TEST_COMMON_HDR_H
#define TEST_COMMON_HDR_H

#include <math.h>
#include <stdlib.h>

#define RUN_TEST(x) do { \
if ((x)) { \
printf("Test passed on line %u with condition " # x "\r\n", (unsigned)__LINE__); \
} else { \
printf("Test FAILED on line %u with condition " # x "\r\n", (unsigned)__LINE__ ); \
exit(1); \
} \
} while (0)
#define FLT_IS_EQUAL(x, y) (fabs((double)(x) - (double)(y)) < 0.00001)
#define INT_IS_EQUAL(x, y) ((int)((x) == (y)))

#endif /* TEST_COMMON_HDR_H */
69 changes: 69 additions & 0 deletions examples/test_time.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* This example uses direct processing function,
* to process dummy PUBX TIME packets from GPS receiver
*/
#include <string.h>
#include <stdio.h>
#include "gps/gps.h"
#include "test_common.h"

#if ! GPS_CFG_STATEMENT_PUBX_TIME
#error "this test must be compiled with -DGPS_CFG_STATEMENT_PUBX_TIME=1"
#endif /* ! GPS_CFG_STATEMENT_PUBX_TIME */

/* GPS handle */
gps_t hgps;

/**
* \brief Dummy data from GPS receiver
*/
const char
gps_rx_data_A[] = ""
"$PUBX,04*37\r\n"
"$PUBX,04,073731.00,091202,113851.00,1196,15D,1930035,-2660.664,43*71\r\n"
"";
const char
gps_rx_data_B[] = ""
"$PUBX,04,200714.00,230320,158834.00,2098,18,536057,257.043,16*12\r\b"
"";


/**
* \brief Run the test of raw input data
*/
void
run_tests() {
gps_init(&hgps); /* Init GPS */

/* Process and test block A */
gps_process(&hgps, gps_rx_data_A, strlen(gps_rx_data_A));

RUN_TEST(INT_IS_EQUAL(hgps.hours, 7));
RUN_TEST(INT_IS_EQUAL(hgps.minutes, 37));
RUN_TEST(INT_IS_EQUAL(hgps.seconds, 31));
RUN_TEST(INT_IS_EQUAL(hgps.date, 9));
RUN_TEST(INT_IS_EQUAL(hgps.month, 12));
RUN_TEST(INT_IS_EQUAL(hgps.year, 2));
RUN_TEST(FLT_IS_EQUAL(hgps.utc_tow, 113851.00));
RUN_TEST(INT_IS_EQUAL(hgps.utc_wk, 1196));
RUN_TEST(INT_IS_EQUAL(hgps.leap_sec, 15));
RUN_TEST(INT_IS_EQUAL(hgps.clk_bias, 1930035));
RUN_TEST(FLT_IS_EQUAL(hgps.clk_drift, -2660.664));
RUN_TEST(INT_IS_EQUAL(hgps.tp_gran, 43));

/* Process and test block B */
gps_process(&hgps, gps_rx_data_B, strlen(gps_rx_data_B));

RUN_TEST(INT_IS_EQUAL(hgps.hours, 20));
RUN_TEST(INT_IS_EQUAL(hgps.minutes, 7));
RUN_TEST(INT_IS_EQUAL(hgps.seconds, 14));
RUN_TEST(INT_IS_EQUAL(hgps.date, 23));
RUN_TEST(INT_IS_EQUAL(hgps.month, 3));
RUN_TEST(INT_IS_EQUAL(hgps.year, 20));
RUN_TEST(FLT_IS_EQUAL(hgps.utc_tow, 158834.00));
RUN_TEST(INT_IS_EQUAL(hgps.utc_wk, 2098));
RUN_TEST(INT_IS_EQUAL(hgps.leap_sec, 18));
RUN_TEST(INT_IS_EQUAL(hgps.clk_bias, 536057));
RUN_TEST(FLT_IS_EQUAL(hgps.clk_drift, 257.043));
RUN_TEST(INT_IS_EQUAL(hgps.tp_gran, 16));
}
90 changes: 82 additions & 8 deletions gps_nmea_parser/src/gps/gps.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@
#define R2D(x) FLT(FLT(x) * FLT(57.29577951308232))/*!< Radians to degrees */
#define EARTH_RADIUS FLT(6371.0) /*!< Earth radius in units of kilometers */

#define STAT_UNKNOWN 0
#define STAT_GGA 1
#define STAT_GSA 2
#define STAT_GSV 3
#define STAT_RMC 4

#define CRC_ADD(_gh, ch) (_gh)->p.crc_calc ^= (uint8_t)(ch)
#define TERM_ADD(_gh, ch) do { \
if ((_gh)->p.term_pos < (sizeof((_gh)->p.term_str) - 1)) { \
Expand Down Expand Up @@ -152,6 +146,10 @@ parse_term(gps_t* gh) {
} else if (!strncmp(gh->p.term_str, "$GPRMC", 6) || !strncmp(gh->p.term_str, "$GNRMC", 6)) {
gh->p.stat = STAT_RMC;
#endif /* GPS_CFG_STATEMENT_GPRMC */
#if GPS_CFG_STATEMENT_PUBX
} else if (!strncmp(gh->p.term_str, "$PUBX", 5)) {
gh->p.stat = STAT_UBX;
#endif /* GPS_CFG_STATEMENT_PUBX */
} else {
gh->p.stat = STAT_UNKNOWN; /* Invalid statement for library */
}
Expand Down Expand Up @@ -281,6 +279,56 @@ parse_term(gps_t* gh) {
default: break;
}
#endif /* GPS_CFG_STATEMENT_GPRMC */
#if GPS_CFG_STATEMENT_PUBX
} else if (gh->p.stat == STAT_UBX) { /* Disambiguate generic PUBX statement */
if (gh->p.term_str[0] == '0' && gh->p.term_str[1] == '4') {
gh->p.stat = STAT_UBX_TIME;
}
#if GPS_CFG_STATEMENT_PUBX_TIME
} else if (gh->p.stat == STAT_UBX_TIME) { /* Process PUBX (uBlox) TIME statement */
switch (gh->p.term_num) {
case 2: /* Process UTC time; ignore fractions of seconds */
gh->p.data.time.hours = 10 * CTN(gh->p.term_str[0]) + CTN(gh->p.term_str[1]);
gh->p.data.time.minutes = 10 * CTN(gh->p.term_str[2]) + CTN(gh->p.term_str[3]);
gh->p.data.time.seconds = 10 * CTN(gh->p.term_str[4]) + CTN(gh->p.term_str[5]);
break;
case 3: /* Process UTC date */
gh->p.data.time.date = 10 * CTN(gh->p.term_str[0]) + CTN(gh->p.term_str[1]);
gh->p.data.time.month = 10 * CTN(gh->p.term_str[2]) + CTN(gh->p.term_str[3]);
gh->p.data.time.year = 10 * CTN(gh->p.term_str[4]) + CTN(gh->p.term_str[5]);
break;
case 4: /* Process UTC TimeOfWeek */
gh->p.data.time.utc_tow = parse_float_number(gh, NULL);
break;
case 5: /* Process UTC WeekNumber */
gh->p.data.time.utc_wk = parse_number(gh, NULL);
break;
case 6: /* Process UTC leap seconds */
/* Accomodate a 2- or 3-digit leap second count;
* a trailing 'D' means this is the firmware's default value.
*/
if (gh->p.term_str[2] == 'D' || gh->p.term_str[2] == '\0') {
gh->p.data.time.leap_sec = 10 * CTN(gh->p.term_str[0])
+ CTN(gh->p.term_str[1]);
} else {
gh->p.data.time.leap_sec = 100 * CTN(gh->p.term_str[0])
+ 10 * CTN(gh->p.term_str[1])
+ CTN(gh->p.term_str[2]);
}
break;
case 7: /* Process clock bias */
gh->p.data.time.clk_bias = parse_number(gh, NULL);
break;
case 8: /* Process clock drift */
gh->p.data.time.clk_drift = parse_float_number(gh, NULL);
break;
case 9: /* Process time pulse granularity */
gh->p.data.time.tp_gran = parse_number(gh, NULL);
break;
default: break;
}
#endif /* GPS_CFG_STATEMENT_PUBX_TIME */
#endif /* GPS_CFG_STATEMENT_PUBX */
}
return 1;
}
Expand Down Expand Up @@ -339,6 +387,21 @@ copy_from_tmp_memory(gps_t* gh) {
gh->month = gh->p.data.rmc.month;
gh->year = gh->p.data.rmc.year;
#endif /* GPS_CFG_STATEMENT_GPRMC */
#if GPS_CFG_STATEMENT_PUBX_TIME
} else if (gh->p.stat == STAT_UBX_TIME) {
gh->hours = gh->p.data.time.hours;
gh->minutes = gh->p.data.time.minutes;
gh->seconds = gh->p.data.time.seconds;
gh->date = gh->p.data.time.date;
gh->month = gh->p.data.time.month;
gh->year = gh->p.data.time.year;
gh->utc_tow = gh->p.data.time.utc_tow;
gh->utc_wk = gh->p.data.time.utc_wk;
gh->leap_sec = gh->p.data.time.leap_sec;
gh->clk_bias = gh->p.data.time.clk_bias;
gh->clk_drift = gh->p.data.time.clk_drift;
gh->tp_gran = gh->p.data.time.tp_gran;
#endif /* GPS_CFG_STATEMENT_PUBX_TIME */
}
return 1;
}
Expand All @@ -359,13 +422,18 @@ gps_init(gps_t* gh) {
* \param[in] gh: GPS handle structure
* \param[in] data: Received data
* \param[in] len: Number of bytes to process
* \param[in] evt_fn: Event function to notify application layer
* \return `1` on success, `0` otherwise
*/
uint8_t
#if GPS_CFG_STATUS || __DOXYGEN__
gps_process(gps_t* gh, const void* data, size_t len, gps_process_fn evt_fn) {
#else /* GPS_CFG_STATUS */
gps_process(gps_t* gh, const void* data, size_t len) {
#endif /* !GPS_CFG_STATUS */
const uint8_t* d = data;

while (len--) { /* Process all bytes */
for (; len > 0; ++d, --len) { /* Process all bytes */
if (*d == '$') { /* Check for beginning of NMEA line */
memset(&gh->p, 0x00, sizeof(gh->p));/* Reset private memory */
TERM_ADD(gh, *d); /* Add character to term */
Expand All @@ -381,14 +449,20 @@ gps_process(gps_t* gh, const void* data, size_t len) {
if (check_crc(gh)) { /* Check for CRC result */
/* CRC is OK, in theory we can copy data from statements to user data */
copy_from_tmp_memory(gh); /* Copy memory from temporary to user memory */
#if GPS_CFG_STATUS
if (evt_fn != NULL) {
evt_fn(gh->p.stat);
}
} else if (evt_fn != NULL) {
evt_fn(STAT_CHECKSUM_FAIL);
#endif /* GPS_CFG_STATUS */
}
} else {
if (!gh->p.star) { /* Add to CRC only if star not yet detected */
CRC_ADD(gh, *d); /* Add to CRC */
}
TERM_ADD(gh, *d); /* Add character to term */
}
d++; /* Process next character */
}
return 1;
}
Expand Down

0 comments on commit 3595fb9

Please sign in to comment.