From 97d68bf4d99a4ca0cb352f3b1ab27c5e1691003e Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 30 Nov 2020 15:47:03 +0100 Subject: [PATCH 01/80] Create FUNDING.yml --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..77b3607 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +custom: ['paypal.me/tilz0R'] From 69c97d4e436fee9d0bc8399c8aeed80047949710 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 30 Nov 2020 16:00:49 +0100 Subject: [PATCH 02/80] Add option to ignore user apps with uncommented macro --- lwgps/src/include/lwgps/lwgps_opt.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index 76f470a..a042ba2 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -34,6 +34,9 @@ #ifndef LWGPS_HDR_OPT_H #define LWGPS_HDR_OPT_H +/* Uncomment to ignore user options (or set macro in compiler flags) */ +/* #define LWGPS_IGNORE_USER_OPTS */ + /* Include application options */ #ifndef LWGPS_IGNORE_USER_OPTS #include "lwgps_opts.h" From 72ba7904215a67e879b419b9e717851f15e83165 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 30 Nov 2020 21:21:04 +0100 Subject: [PATCH 03/80] Add donate button --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 5ba914b..cd210ed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,7 +8,7 @@ LwGPS is lightweight, platform independent library to parse NMEA statements from .. rst-class:: center .. rst-class:: index_links - :ref:`download_library` :ref:`getting_started` `Open Github `_ + :ref:`download_library` :ref:`getting_started` `Open Github `_ `Donate `_ Features ^^^^^^^^ From 199cf9d9d3b320867003e0a0743e02c5852da86a Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 5 Dec 2020 01:24:34 +0100 Subject: [PATCH 04/80] Add logo on all --- docs/conf.py | 2 +- docs/index.rst | 3 +++ docs/static/images/logo.drawio | 1 + docs/static/images/logo.svg | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 docs/static/images/logo.drawio create mode 100644 docs/static/images/logo.svg diff --git a/docs/conf.py b/docs/conf.py index 610e5a4..4ccb515 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -99,7 +99,7 @@ 'includehidden': True, 'titles_only': False } -html_logo = 'static/images/logo_tm.png' +html_logo = 'static/images/logo.svg' github_url = 'https://github.com/MaJerle/lwgps' html_baseurl = 'https://docs.majerle.eu/projects/lwgps/' diff --git a/docs/index.rst b/docs/index.rst index cd210ed..a792a0b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,6 +5,9 @@ Welcome to the documentation for version |version|. LwGPS is lightweight, platform independent library to parse NMEA statements from GPS receivers. It is highly optimized for embedded systems. +.. image:: static/images/logo.svg + :align: center + .. rst-class:: center .. rst-class:: index_links diff --git a/docs/static/images/logo.drawio b/docs/static/images/logo.drawio new file mode 100644 index 0000000..19871f4 --- /dev/null +++ b/docs/static/images/logo.drawio @@ -0,0 +1 @@ +jZJNb8MgDIZ/TY6VkpB067Vd10nrqkk59IyCG1AhRJSMdL9+ZDH5UDVpJ/BjY+B9HZGd6g6GNvxDM5BRGrMuIi9RmibxU+aXntwHssnzAVRGMCyaQCG+IZxE2goGt0Wh1Vpa0SxhqesaSrtg1BjtlmUXLZe3NrSCB1CUVD7Ss2CWD/Q5jyf+BqLi4eYkxoyioRjBjVOm3QyRfUR2Rms77FS3A9mLF3QZzr3+kR0fZqC2/zlwWrEMNsodT6rdZpv3izwnK+zyRWWLHz66w2eBL7b3IIPRbc2g75REZOu4sFA0tOyzzhvvGbdKYvpmjb6Ocq09uejaorekj0ctYh88fiS8CoyFbobwYwfQCqy5+xLMkgynCqcsDbGbPEvWaASf+RV8pDgm1dh6UtJvUMwQTqb95majT/Y/ \ No newline at end of file diff --git a/docs/static/images/logo.svg b/docs/static/images/logo.svg new file mode 100644 index 0000000..d98aadc --- /dev/null +++ b/docs/static/images/logo.svg @@ -0,0 +1,3 @@ + + +
LwGPS
LwGPS
\ No newline at end of file From aa788f3c19bdd5030d7302d9ebd44f3bc8a28de0 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 5 Dec 2020 08:58:16 +0100 Subject: [PATCH 05/80] Add v prefix in version --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 4ccb515..4f2f70b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -27,7 +27,7 @@ author = 'Tilen MAJERLE' # The full version, including alpha/beta/rc tags -version = '2.1.0' +version = 'v2.1.0' # Try to get branch at which this is running # and try to determine which version to display in sphinx From adce7a203268ca809fa61e6e286e62ff25edeb34 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 12 Dec 2020 10:57:23 +0100 Subject: [PATCH 06/80] Generic docs update --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 4f2f70b..4960511 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -112,7 +112,7 @@ 'css/custom.css', ] html_js_files = [ - 'https://kit.fontawesome.com/3102794088.js' + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css' ] master_doc = 'index' From ceba10e5616b6419a3b61ea2d608ad345d49b1e2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 27 Feb 2021 21:26:48 +0100 Subject: [PATCH 07/80] added cmake support --- .gitignore | 1 - CMakeLists.txt | 37 ++++++++++++++++++++++++++ examples/CMakeLists.txt | 0 lwgps/CMakeLists.txt | 1 + lwgps/src/CMakeLists.txt | 2 ++ lwgps/src/include/CMakeLists.txt | 7 +++++ lwgps/src/include/lwgps/CMakeLists.txt | 3 +++ lwgps/src/lwgps/CMakeLists.txt | 3 +++ 8 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 CMakeLists.txt create mode 100644 examples/CMakeLists.txt create mode 100644 lwgps/CMakeLists.txt create mode 100644 lwgps/src/CMakeLists.txt create mode 100644 lwgps/src/include/CMakeLists.txt create mode 100644 lwgps/src/include/lwgps/CMakeLists.txt create mode 100644 lwgps/src/lwgps/CMakeLists.txt diff --git a/.gitignore b/.gitignore index e5e5539..dd30ca7 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,6 @@ *.uvoptx *.__i *.i -*.txt !docs/*.txt RTE/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..251a8f6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,37 @@ +################################################################################ +# Lightweight GPS (lwgps) CMake support +################################################################################ +# The lwgps library can be configured with a lwgps_opts.h file. +# If such a file is used, the user should set LWGPS_CONFIG_PATH +# so that is is included properly. +# Other than that, only two steps are necessary to compile and link against LWGPS: +# 1. Use add_subdirectory to add the LWGPS folder +# 2. Link against lwgps with target_link_libraries +################################################################################ +cmake_minimum_required(VERSION 3.13) + +set(LIB_LWGPS_NAME lwgps) + +add_library(${LIB_LWGPS_NAME}) + +add_subdirectory(${LIB_LWGPS_NAME}) +add_subdirectory(examples) + +# The project CMakeLists can set a LWGPS_CONFIG_PATH path including the lwgps_opts.h file +# and add it. +if(NOT LWGPS_CONFIG_PATH) + message(STATUS "Lightweight GPS configuration path not set.") +endif() + +# Extract the absolute path of the provided configuration path +if(IS_ABSOLUTE ${LWGPS_CONFIG_PATH}) + set(LWGPS_CONFIG_PATH_ABSOLUTE ${LWGPS_CONFIG_PATH}) +else() + get_filename_component(LWGPS_CONFIG_PATH_ABSOLUTE + ${LWGPS_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR} + ) +endif() + +target_include_directories(${LIB_LWGPS_NAME} PRIVATE + ${LWGPS_CONFIG_PATH_ABSOLUTE} +) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/lwgps/CMakeLists.txt b/lwgps/CMakeLists.txt new file mode 100644 index 0000000..130b119 --- /dev/null +++ b/lwgps/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(src) \ No newline at end of file diff --git a/lwgps/src/CMakeLists.txt b/lwgps/src/CMakeLists.txt new file mode 100644 index 0000000..9172260 --- /dev/null +++ b/lwgps/src/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(include) +add_subdirectory(lwgps) diff --git a/lwgps/src/include/CMakeLists.txt b/lwgps/src/include/CMakeLists.txt new file mode 100644 index 0000000..52fc4ca --- /dev/null +++ b/lwgps/src/include/CMakeLists.txt @@ -0,0 +1,7 @@ +target_include_directories(${LIB_LWGPS_NAME} INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_include_directories(${LIB_LWGPS_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) \ No newline at end of file diff --git a/lwgps/src/include/lwgps/CMakeLists.txt b/lwgps/src/include/lwgps/CMakeLists.txt new file mode 100644 index 0000000..0c0febb --- /dev/null +++ b/lwgps/src/include/lwgps/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${LIB_LWGPS_NAME} PRIVATE + lwgps.c +) \ No newline at end of file diff --git a/lwgps/src/lwgps/CMakeLists.txt b/lwgps/src/lwgps/CMakeLists.txt new file mode 100644 index 0000000..0c0febb --- /dev/null +++ b/lwgps/src/lwgps/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${LIB_LWGPS_NAME} PRIVATE + lwgps.c +) \ No newline at end of file From 2b741bd5c8721ee224f06316718bf691929c051a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 27 Feb 2021 21:43:03 +0100 Subject: [PATCH 08/80] better explanation --- CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 251a8f6..817af9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,11 @@ # Lightweight GPS (lwgps) CMake support ################################################################################ # The lwgps library can be configured with a lwgps_opts.h file. -# If such a file is used, the user should set LWGPS_CONFIG_PATH -# so that is is included properly. +# If such a file is used, the user should set the LWGPS_CONFIG_PATH path variable where +# the configuration file is located so that is is included properly. +# # Other than that, only two steps are necessary to compile and link against LWGPS: -# 1. Use add_subdirectory to add the LWGPS folder +# 1. Use add_subdirectory to add the lwgps folder # 2. Link against lwgps with target_link_libraries ################################################################################ cmake_minimum_required(VERSION 3.13) From 8c16e298ca03128a109d9ba159ccce1788836382 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 27 Feb 2021 21:49:05 +0100 Subject: [PATCH 09/80] updated docs --- docs/get-started/index.rst | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index 83a0aed..77141a2 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -45,8 +45,9 @@ Update cloned to latest version This is preferred option to use when you want to evaluate library and run prepared examples. Repository consists of multiple submodules which can be automatically downloaded when cloning and pulling changes from root repository. -Add library to project -^^^^^^^^^^^^^^^^^^^^^^ + +Add library to project - Generic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ At this point it is assumed that you have successfully download library, either cloned it or from releases page. @@ -56,6 +57,18 @@ At this point it is assumed that you have successfully download library, either * Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to project folder and rename it to ``lwgps_opts.h`` * Build the project +Add library to project - CMake +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Including the library with CMake is very easy. + +* Add the ``lwgps`` folder with ``add_subdirectory`` +* Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to project folder and rename it to ``lwgps_opts.h`` +* Set the ``LWGPS_CONFIG_PATH`` path variable containing the ``lwgps_opts.h`` file + in the project ``CMakeLists.txt`` +* Link your project againt the ``lwgps`` library with ``target_link_libraries`` +* The include directory should be set automatically by CMake + Configuration file ^^^^^^^^^^^^^^^^^^ From 59091469ab24fdf46651f77795a2798e80d0eb0f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 28 Feb 2021 16:13:45 +0100 Subject: [PATCH 10/80] some smaller form stuff --- CMakeLists.txt | 1 + docs/get-started/index.rst | 9 +++++---- lwgps/CMakeLists.txt | 2 +- lwgps/src/CMakeLists.txt | 1 + lwgps/src/include/CMakeLists.txt | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 817af9f..4f59873 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,3 +36,4 @@ endif() target_include_directories(${LIB_LWGPS_NAME} PRIVATE ${LWGPS_CONFIG_PATH_ABSOLUTE} ) + diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index 77141a2..59a9a19 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -62,11 +62,12 @@ Add library to project - CMake Including the library with CMake is very easy. -* Add the ``lwgps`` folder with ``add_subdirectory`` -* Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to project folder and rename it to ``lwgps_opts.h`` +* Add the ``lwgps`` folder with ``add_subdirectory`` +* Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to the project folder and rename it + to ``lwgps_opts.h`` * Set the ``LWGPS_CONFIG_PATH`` path variable containing the ``lwgps_opts.h`` file - in the project ``CMakeLists.txt`` -* Link your project againt the ``lwgps`` library with ``target_link_libraries`` + in the project ``CMakeLists.txt`` +* Link your project against the ``lwgps`` library with ``target_link_libraries`` * The include directory should be set automatically by CMake Configuration file diff --git a/lwgps/CMakeLists.txt b/lwgps/CMakeLists.txt index 130b119..febd4f0 100644 --- a/lwgps/CMakeLists.txt +++ b/lwgps/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(src) \ No newline at end of file +add_subdirectory(src) diff --git a/lwgps/src/CMakeLists.txt b/lwgps/src/CMakeLists.txt index 9172260..970833c 100644 --- a/lwgps/src/CMakeLists.txt +++ b/lwgps/src/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(include) add_subdirectory(lwgps) + diff --git a/lwgps/src/include/CMakeLists.txt b/lwgps/src/include/CMakeLists.txt index 52fc4ca..b294ed6 100644 --- a/lwgps/src/include/CMakeLists.txt +++ b/lwgps/src/include/CMakeLists.txt @@ -4,4 +4,4 @@ target_include_directories(${LIB_LWGPS_NAME} INTERFACE target_include_directories(${LIB_LWGPS_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} -) \ No newline at end of file +) From d276f9722d1311b552e7c99ee5b03a68487a0fc5 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 28 Feb 2021 16:15:05 +0100 Subject: [PATCH 11/80] added newlines --- lwgps/src/include/lwgps/CMakeLists.txt | 2 +- lwgps/src/lwgps/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lwgps/src/include/lwgps/CMakeLists.txt b/lwgps/src/include/lwgps/CMakeLists.txt index 0c0febb..d68efc2 100644 --- a/lwgps/src/include/lwgps/CMakeLists.txt +++ b/lwgps/src/include/lwgps/CMakeLists.txt @@ -1,3 +1,3 @@ target_sources(${LIB_LWGPS_NAME} PRIVATE lwgps.c -) \ No newline at end of file +) diff --git a/lwgps/src/lwgps/CMakeLists.txt b/lwgps/src/lwgps/CMakeLists.txt index 0c0febb..d68efc2 100644 --- a/lwgps/src/lwgps/CMakeLists.txt +++ b/lwgps/src/lwgps/CMakeLists.txt @@ -1,3 +1,3 @@ target_sources(${LIB_LWGPS_NAME} PRIVATE lwgps.c -) \ No newline at end of file +) From 6fbcf3485e8d67380c770b18c7ead1335df78331 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 28 Feb 2021 22:19:13 +0100 Subject: [PATCH 12/80] Add option to disable CRC calculation --- lwgps/src/include/lwgps/lwgps.h | 2 ++ lwgps/src/include/lwgps/lwgps_opt.h | 9 +++++++++ lwgps/src/lwgps/lwgps.c | 8 ++++++++ 3 files changed, 19 insertions(+) diff --git a/lwgps/src/include/lwgps/lwgps.h b/lwgps/src/include/lwgps/lwgps.h index ed0463d..31c36c5 100644 --- a/lwgps/src/include/lwgps/lwgps.h +++ b/lwgps/src/include/lwgps/lwgps.h @@ -159,7 +159,9 @@ typedef struct { uint8_t star; /*!< Star detected flag */ +#if LWGPS_CFG_CRC uint8_t crc_calc; /*!< Calculated CRC string */ +#endif /* LWGPS_CFG_CRC */ union { uint8_t dummy; /*!< Dummy byte */ diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index a042ba2..a86a35f 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -158,6 +158,15 @@ extern "C" { #define LWGPS_CFG_STATEMENT_PUBX_TIME 0 #endif +/** + * \brief Enables `1` or disables `0` CRC calculation and check + * + * \note When not enabled, CRC check is ignored + */ +#ifndef LWGPS_CFG_CRC +#define LWGPS_CFG_CRC 1 +#endif + /* Guard against accidental parser breakage */ #if LWGPS_CFG_STATEMENT_PUBX_TIME && !LWGPS_CFG_STATEMENT_PUBX #error LWGPS_CFG_STATEMENT_PUBX must be enabled when enabling LWGPS_CFG_STATEMENT_PUBX_TIME diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index 5ae47f3..195d47d 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -41,7 +41,11 @@ #define R2D(x) FLT(FLT(x) * FLT(57.29577951308232))/*!< Radians to degrees */ #define EARTH_RADIUS FLT(6371.0) /*!< Earth radius in units of kilometers */ +#if LWGPS_CFG_CRC #define CRC_ADD(_gh, ch) (_gh)->p.crc_calc ^= (uint8_t)(ch) +#else +#define CRC_ADD(_gh, ch) +#endif /* LWGPS_CFG_CRC */ #define TERM_ADD(_gh, ch) do { \ if ((_gh)->p.term_pos < (sizeof((_gh)->p.term_str) - 1)) { \ (_gh)->p.term_str[(_gh)->p.term_pos] = (ch);\ @@ -346,6 +350,7 @@ prv_parse_term(lwgps_t* gh) { return 1; } +#if LWGPS_CFG_CRC /** * \brief Compare calculated CRC with received CRC * \param[in] gh: GPS handle @@ -357,6 +362,9 @@ prv_check_crc(lwgps_t* gh) { crc = (uint8_t)((CHTN(gh->p.term_str[0]) & 0x0F) << 0x04) | (CHTN(gh->p.term_str[1]) & 0x0F); /* Convert received CRC from string (hex) to number */ return gh->p.crc_calc == crc; /* They must match! */ } +#else +#define prv_check_crc(_gh) (1) +#endif /* LWGPS_CFG_CRC */ /** * \brief Copy temporary memory to user memory From b13fc4113338580a744455a28a4f32c7c4b43360 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 29 Mar 2021 14:08:32 +0200 Subject: [PATCH 13/80] Add Changelog --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..19d06c8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +## v2.1.0 + +- Add configuration settings to be consistend with other LwXX libraries +- Apply code style settings with Artistic style options + +## v2.0.0 + +- Break compatibility with v1.x +- Function prefix set to `lwgps_` +- Macros prefix set to `LWGPS_` +- Added support for PUBX Ublox statement + +## v1.1.0 + +- Use pre-increment instead of post-increment +- Remove buffer library and propose ringbuff instead +- Other code style enhancements + +## v1.0.0 + +- Initial release + From 0cf2e6b6af5570a5469bba63fd265988a6690620 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Thu, 8 Apr 2021 19:07:31 +0200 Subject: [PATCH 14/80] Automatic version parser for sphinx --- docs/conf.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 4960511..5586eea 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,27 +26,31 @@ copyright = '2020, Tilen MAJERLE' author = 'Tilen MAJERLE' -# The full version, including alpha/beta/rc tags -version = 'v2.1.0' - # Try to get branch at which this is running # and try to determine which version to display in sphinx +# Version is using git tag if on master or "latest-develop" if on develop branch +version = '' git_branch = '' + +# Get current branch res = os.popen('git branch').read().strip() for line in res.split("\n"): if line[0] == '*': git_branch = line[1:].strip() # Decision for display version -try: - if git_branch.index('develop') >= 0: - version = "latest-develop" -except Exception: - print("Exception for index check") - -# For debugging purpose +if git_branch == 'master' or git_branch == 'main': + version = os.popen('git describe --tags --abbrev=0').read().strip() + if version == '': + version = 'v0.0.0' +elif git_branch == 'develop': + version = 'latest-develop' +else: + version = 'branch-' + git_branch + +# For debugging purpose only print("GIT BRANCH: " + git_branch) -print("VERSION: " + version) +print("GIT VERSION: " + version) # -- General configuration --------------------------------------------------- From 1d43ed3c1d5bdb32ca7eeeaa3bf05b67c19f01f8 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 9 Apr 2021 20:45:16 +0200 Subject: [PATCH 15/80] conf.py update --- docs/conf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5586eea..f975ed0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -39,11 +39,12 @@ git_branch = line[1:].strip() # Decision for display version -if git_branch == 'master' or git_branch == 'main': +git_branch = git_branch.replace('(HEAD detached at ', '').replace(')', '') +if git_branch.find('master') >= 0 or git_branch.find('main') >= 0: version = os.popen('git describe --tags --abbrev=0').read().strip() if version == '': version = 'v0.0.0' -elif git_branch == 'develop': +elif git_branch.find('develop') != -1 and not (git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0): version = 'latest-develop' else: version = 'branch-' + git_branch From b7be2f0946a1bff49ca38797b5d580ebc6488ccb Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 10 Apr 2021 11:33:09 +0200 Subject: [PATCH 16/80] Fix requirements for all repositories --- docs/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index c0ffd67..eb5e0fd 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,7 @@ breathe>=4.9.1 colorama -docutils>=0.14 -sphinx>=2.0.1 +docutils==0.16 +sphinx>=3.5.1 sphinx_rtd_theme sphinx-tabs sphinxcontrib-svg2pdfconverter From 205b444320aeef77b443cc7ae75c11f9429fe3e7 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 11 Apr 2021 12:10:20 +0200 Subject: [PATCH 17/80] Add release workflow --- .github/workflows/release.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c4e4ac0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,27 @@ +on: + push: + # Sequence of patterns matched against refs/tags + tags: + - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 + +name: Create Release + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + body: | + See the CHANGELOG.md + draft: false + prerelease: false \ No newline at end of file From 7cbb544012e317e7edb9acba9a82c2b15559daa7 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Tue, 13 Apr 2021 21:56:16 +0200 Subject: [PATCH 18/80] Update getting started --- docs/get-started/index.rst | 67 ++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index 59a9a19..7e3c670 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -3,6 +3,9 @@ Getting started =============== +Getting started may be the most challenging part of every new library. +This guide is describing how to start with the library quickly and effectively + .. _download_library: Download library @@ -10,8 +13,11 @@ Download library Library is primarly hosted on `Github `_. -* Download latest release from `releases area `_ on Github -* Clone `develop` branch for latest development +You can get it with: + +* Downloading latest release from `releases area `_ on Github +* Cloning ``master`` branch for latest stable version +* Cloning ``develop`` branch for latest development Download from releases ********************** @@ -24,7 +30,9 @@ Clone from Github First-time clone """""""""""""""" -* Download and install ``git`` if not already +This is used when you do not have yet local copy on your machine. + +* Make sure ``git`` is installed. * Open console and navigate to path in the system to clone repository to. Use command ``cd your_path`` * Clone repository with one of available ``3`` options @@ -38,63 +46,58 @@ Update cloned to latest version """"""""""""""""""""""""""""""" * Open console and navigate to path in the system where your resources repository is. Use command ``cd your_path`` -* Run ``git pull origin master --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules +* Run ``git pull origin master --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``master`` branch +* Run ``git pull origin develop --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``develop`` branch * Run ``git submodule foreach git pull origin master`` to update & merge all submodules .. note:: - This is preferred option to use when you want to evaluate library and run prepared examples. - Repository consists of multiple submodules which can be automatically downloaded when cloning and pulling changes from root repository. + This is preferred option to use when you want to evaluate library and run prepared examples. + Repository consists of multiple submodules which can be automatically downloaded when cloning and pulling changes from root repository. - -Add library to project - Generic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Add library to project +^^^^^^^^^^^^^^^^^^^^^^ At this point it is assumed that you have successfully download library, either cloned it or from releases page. +Next step is to add the library to the project, by means of source files to compiler inputs and header files in search path -* Copy ``lwgps`` folder to your project -* Add ``lwgps/src/include`` folder to `include path` of your toolchain -* Add source files from ``lwgps/src/`` folder to toolchain build +* Copy ``lwgps`` folder to your project, it contains library files +* Add ``lwgps/src/include`` folder to `include path` of your toolchain. This is where `C/C++` compiler can find the files during compilation process. Usually using ``-I`` flag +* Add source files from ``lwgps/src/`` folder to toolchain build. These files are built by `C/C++` compiler * Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to project folder and rename it to ``lwgps_opts.h`` * Build the project -Add library to project - CMake -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Including the library with CMake is very easy. - -* Add the ``lwgps`` folder with ``add_subdirectory`` -* Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to the project folder and rename it - to ``lwgps_opts.h`` -* Set the ``LWGPS_CONFIG_PATH`` path variable containing the ``lwgps_opts.h`` file - in the project ``CMakeLists.txt`` -* Link your project against the ``lwgps`` library with ``target_link_libraries`` -* The include directory should be set automatically by CMake - Configuration file ^^^^^^^^^^^^^^^^^^ +Configuration file is used to overwrite default settings defined for the essential use case. Library comes with template config file, which can be modified according to needs. -This file shall be named ``lwgps_opts.h`` and its default template looks like the one below. +and it should be copied (or simply renamed in-place) and named ``lwgps_opts.h`` .. note:: Default configuration template file location: ``lwgps/src/include/lwgps/lwgps_opts_template.h``. - File must be renamed to ``lwgps_opts.h`` first and then copied to the project directory (or simply renamed in-place) where compiler + File must be renamed to ``lwgps_opts.h`` first and then copied to the project directory where compiler include paths have access to it by using ``#include "lwgps_opts.h"``. -.. tip:: - Check :ref:`api_lwgps_opt` section for possible configuration settings +List of configuration options are available in the :ref:`api_lwgps_opt` section. +If any option is about to be modified, it should be done in configuration file .. literalinclude:: ../../lwgps/src/include/lwgps/lwgps_opts_template.h :language: c :linenos: - :caption: Template options file + :caption: Template configuration file + +.. note:: + If you prefer to avoid using configuration file, application must define + a global symbol ``LWGPS_IGNORE_USER_OPTS``, visible across entire application. + This can be achieved with ``-D`` compiler option. Minimal example code ^^^^^^^^^^^^^^^^^^^^ -Run below example to test and verify library +To verify proper library setup, minimal example has been prepared. +Run it in your main application file to verify its proper execution .. literalinclude:: ../../examples/example.c :language: c :linenos: - :caption: Test verification code \ No newline at end of file + :caption: Absolute minimum example \ No newline at end of file From e85cf0ab219e8ec2ea0e520277cb3e98d26ff6ab Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 20 Aug 2021 11:41:06 +0200 Subject: [PATCH 19/80] simplifying CMakeLists.txt files --- CMakeLists.txt | 31 +++++--------------------- lwgps/src/CMakeLists.txt | 3 --- lwgps/src/include/CMakeLists.txt | 7 ------ lwgps/src/include/lwgps/CMakeLists.txt | 3 --- lwgps/src/lwgps/CMakeLists.txt | 3 --- 5 files changed, 6 insertions(+), 41 deletions(-) delete mode 100644 lwgps/src/CMakeLists.txt delete mode 100644 lwgps/src/include/CMakeLists.txt delete mode 100644 lwgps/src/include/lwgps/CMakeLists.txt delete mode 100644 lwgps/src/lwgps/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f59873..bca4349 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,29 +11,10 @@ ################################################################################ cmake_minimum_required(VERSION 3.13) -set(LIB_LWGPS_NAME lwgps) - -add_library(${LIB_LWGPS_NAME}) - -add_subdirectory(${LIB_LWGPS_NAME}) -add_subdirectory(examples) - -# The project CMakeLists can set a LWGPS_CONFIG_PATH path including the lwgps_opts.h file -# and add it. -if(NOT LWGPS_CONFIG_PATH) - message(STATUS "Lightweight GPS configuration path not set.") +set(LWGPS_LIB_NAME LwGPS) +set(LWGPS_LIB_TARGET ${LIB_LWGPS_NAME}::${LIB_LWGPS_NAME}) +if(NOT (TARGET ${LWGPS_LIB_TARGET})) + add_library(${LWGPS_LIB_TARGET} INTERFACE IMPORTED) + target_sources(${LWGPS_LIB_TARGET} INTERFACE "lwgps/src/lwgps/lwgps.c") + target_include_directories(${LWGPS_LIB_TARGET} INTERFACE "lwgps/src/include/lwgps") endif() - -# Extract the absolute path of the provided configuration path -if(IS_ABSOLUTE ${LWGPS_CONFIG_PATH}) - set(LWGPS_CONFIG_PATH_ABSOLUTE ${LWGPS_CONFIG_PATH}) -else() - get_filename_component(LWGPS_CONFIG_PATH_ABSOLUTE - ${LWGPS_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR} - ) -endif() - -target_include_directories(${LIB_LWGPS_NAME} PRIVATE - ${LWGPS_CONFIG_PATH_ABSOLUTE} -) - diff --git a/lwgps/src/CMakeLists.txt b/lwgps/src/CMakeLists.txt deleted file mode 100644 index 970833c..0000000 --- a/lwgps/src/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_subdirectory(include) -add_subdirectory(lwgps) - diff --git a/lwgps/src/include/CMakeLists.txt b/lwgps/src/include/CMakeLists.txt deleted file mode 100644 index b294ed6..0000000 --- a/lwgps/src/include/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -target_include_directories(${LIB_LWGPS_NAME} INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR} -) - -target_include_directories(${LIB_LWGPS_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} -) diff --git a/lwgps/src/include/lwgps/CMakeLists.txt b/lwgps/src/include/lwgps/CMakeLists.txt deleted file mode 100644 index d68efc2..0000000 --- a/lwgps/src/include/lwgps/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_LWGPS_NAME} PRIVATE - lwgps.c -) diff --git a/lwgps/src/lwgps/CMakeLists.txt b/lwgps/src/lwgps/CMakeLists.txt deleted file mode 100644 index d68efc2..0000000 --- a/lwgps/src/lwgps/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(${LIB_LWGPS_NAME} PRIVATE - lwgps.c -) From 039db0e030b71185bfd6d675348c352c02bd80e9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 20 Aug 2021 11:54:13 +0200 Subject: [PATCH 20/80] this works --- CMakeLists.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bca4349..8520359 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,10 +11,9 @@ ################################################################################ cmake_minimum_required(VERSION 3.13) -set(LWGPS_LIB_NAME LwGPS) -set(LWGPS_LIB_TARGET ${LIB_LWGPS_NAME}::${LIB_LWGPS_NAME}) -if(NOT (TARGET ${LWGPS_LIB_TARGET})) - add_library(${LWGPS_LIB_TARGET} INTERFACE IMPORTED) - target_sources(${LWGPS_LIB_TARGET} INTERFACE "lwgps/src/lwgps/lwgps.c") - target_include_directories(${LWGPS_LIB_TARGET} INTERFACE "lwgps/src/include/lwgps") +set(LWGPS_LIB_NAME lwgps) +if(NOT (TARGET ${LWGPS_LIB_NAME})) + add_library(${LWGPS_LIB_NAME} INTERFACE) + target_sources(${LWGPS_LIB_NAME} INTERFACE "lwgps/src/lwgps/lwgps.c") + target_include_directories(${LWGPS_LIB_NAME} INTERFACE "lwgps/src/include") endif() From 52999ddfe5177493b96b55871961a8a97131596d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 20 Aug 2021 11:55:41 +0200 Subject: [PATCH 21/80] cmakelists doc update --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8520359..43afe4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ # Lightweight GPS (lwgps) CMake support ################################################################################ # The lwgps library can be configured with a lwgps_opts.h file. -# If such a file is used, the user should set the LWGPS_CONFIG_PATH path variable where -# the configuration file is located so that is is included properly. +# If such a file is used, the user should have the path containing this file +# in the target include directories in an upper CMakeLists.txt # # Other than that, only two steps are necessary to compile and link against LWGPS: # 1. Use add_subdirectory to add the lwgps folder From 4e8993b8d8fcd796aa4701762748b466486cdbd8 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Thu, 25 Nov 2021 20:14:43 +0100 Subject: [PATCH 22/80] Add library.json file --- library.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 library.json diff --git a/library.json b/library.json new file mode 100644 index 0000000..29120b8 --- /dev/null +++ b/library.json @@ -0,0 +1,24 @@ +{ + "name": "LwGPS", + "version": "2.1.0", + "description": "Lightweight GPS NMEA statement parser for embedded systems", + "keywords": "lwgps, global, position, satellite, glonass, gps, altitude, embedded, platform, independent", + "repository": { + "type": "git", + "url": "https://github.com/MaJerle/lwgps.git" + }, + "authors": [ + { + "name": "Tilen Majerle", + "email": "tilen@majerle.eu", + "url": "https://majerle.eu" + } + ], + "license": "MIT", + "homepage": "https://github.com/MaJerle/lwgps", + "dependencies": { + + }, + "frameworks": "*", + "platforms": "*" +} \ No newline at end of file From 944c489df536ead914446d922b07d0fd3b721cfe Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 26 Nov 2021 21:21:15 +0100 Subject: [PATCH 23/80] Update release workflow with link to changelog --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4e4ac0..f43a9c1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,6 +22,6 @@ jobs: tag_name: ${{ github.ref }} release_name: Release ${{ github.ref }} body: | - See the CHANGELOG.md + See the [CHANGELOG](CHANGELOG.md) draft: false prerelease: false \ No newline at end of file From f7cf32cf80cd73a64ccef8f205ea229ea6649e36 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 19 Dec 2021 16:03:28 +0100 Subject: [PATCH 24/80] Update export control for Platform.IO --- library.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library.json b/library.json index 29120b8..4b84e06 100644 --- a/library.json +++ b/library.json @@ -20,5 +20,15 @@ }, "frameworks": "*", - "platforms": "*" + "platforms": "*", + "export": { + "exclude": [ + ".github", + "dev", + "docs", + "**/.vs", + "**/Debug", + "build" + ] + } } \ No newline at end of file From 0ae20822feed7b8137f5ba4fd44100b99e2f5f2f Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 24 Dec 2021 13:58:09 +0100 Subject: [PATCH 25/80] Update cmake and add vscode support --- .gitignore | 57 ++++++++++++++++++++++------------- .vscode/c_cpp_properties.json | 24 +++++++++++++++ .vscode/launch.json | 20 ++++++++++++ .vscode/tasks.json | 54 +++++++++++++++++++++++++++++++++ CMakeLists.txt | 52 +++++++++++++++++++++----------- lwgps/CMakeLists.txt | 21 ++++++++++++- 6 files changed, 188 insertions(+), 40 deletions(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.gitignore b/.gitignore index dd30ca7..4674b8a 100644 --- a/.gitignore +++ b/.gitignore @@ -22,27 +22,31 @@ *.uvoptx *.__i *.i +*.txt !docs/*.txt +!CMakeLists.txt RTE/ -# IAR Settings -**/settings/*.crun -**/settings/*.dbgdt -**/settings/*.cspy -**/settings/*.cspy.* -**/settings/*.xcl -**/settings/*.dni -**/settings/*.wsdt -**/settings/*.wspos - -# IAR Debug Exe -**/Exe/*.sim - -# IAR Debug Obj -**/Obj/*.pbd -**/Obj/*.pbd.* -**/Obj/*.pbi -**/Obj/*.pbi.* +*debug + +# IAR Settings +**/settings/*.crun +**/settings/*.dbgdt +**/settings/*.cspy +**/settings/*.cspy.* +**/settings/*.xcl +**/settings/*.dni +**/settings/*.wsdt +**/settings/*.wspos + +# IAR Debug Exe +**/Exe/*.sim + +# IAR Debug Obj +**/Obj/*.pbd +**/Obj/*.pbd.* +**/Obj/*.pbi +**/Obj/*.pbi.* *.TMP /docs_src/x_Doxyfile.doxy @@ -68,6 +72,7 @@ RTE/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ +[Dd]ebug*/ x64/ x86/ bld/ @@ -75,6 +80,7 @@ bld/ [Oo]bj/ [Ll]og/ _build/ +build/ # Visual Studio 2015/2017 cache/options directory .vs/ @@ -273,7 +279,7 @@ ClientBin/ *.publishsettings orleans.codegen.cs -# Including strong name files can present a security risk +# Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk @@ -369,7 +375,7 @@ __pycache__/ # OpenCover UI analysis results OpenCover/ -# Azure Stream Analytics local run output +# Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log @@ -382,4 +388,13 @@ log_file.txt project.ioc mx.scratch *.tilen majerle -*.exe + + +# Altium +Project outputs* +History/ +*.SchDocPreview +*.$$$Preview + +# VSCode projects +project_vscode_compiled.exe \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..7caebce --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,24 @@ +{ + "version": 4, + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}\\dev\\VisualStudio\\", + "${workspaceFolder}\\lwgps\\src\\include\\" + ], + "defines": [ + "WIN32", + "_DEBUG", + "UNICODE", + "_UNICODE", + "LWGPS_DEV" + ], + "compilerPath": "c:\\msys64\\mingw64\\bin\\gcc.exe", + "cStandard": "gnu17", + "cppStandard": "gnu++14", + "intelliSenseMode": "windows-gcc-x86", + "configurationProvider": "ms-vscode.cmake-tools" + } + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5a04de8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(Windows) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}\\build\\LwGPS.exe", + "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..6d1726e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,54 @@ +{ + "version": "2.0.0", + + /* For this builds, you need + * + * - Ninja build system + * - MSYS2 compiler with ninja support + * - C/C++ extension for VSCode + * - CMake-Tools extension for VSCode + */ + "tasks": [ + { + "type": "cppbuild", + "label": "Build project", + "command": "cmake", + "args": ["--build", "\"build\""], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "Re-build project", + "command": "cmake", + "args": ["--build", "\"build\"", "--clean-first", "-v"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + }, + { + "type": "shell", + "label": "Clean project", + "command": "cmake", + "args": ["--build", "\"build\"", "--target", "clean"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "Run application", + "command": "${workspaceFolder}\\build\\LwGPS.exe", + "args": [], + "problemMatcher": [], + }, + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 43afe4f..30fa9f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,35 @@ -################################################################################ -# Lightweight GPS (lwgps) CMake support -################################################################################ -# The lwgps library can be configured with a lwgps_opts.h file. -# If such a file is used, the user should have the path containing this file -# in the target include directories in an upper CMakeLists.txt -# -# Other than that, only two steps are necessary to compile and link against LWGPS: -# 1. Use add_subdirectory to add the lwgps folder -# 2. Link against lwgps with target_link_libraries -################################################################################ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.0.0) -set(LWGPS_LIB_NAME lwgps) -if(NOT (TARGET ${LWGPS_LIB_NAME})) - add_library(${LWGPS_LIB_NAME} INTERFACE) - target_sources(${LWGPS_LIB_NAME} INTERFACE "lwgps/src/lwgps/lwgps.c") - target_include_directories(${LWGPS_LIB_NAME} INTERFACE "lwgps/src/include") -endif() +# Setup project +project(LwGPS VERSION 2.0.1) + +# ------------------------ +# Configuration used if cmake uses this as +# top-level project CMakeLists.txt file +# This is normally used for development purpose only +if (PROJECT_IS_TOP_LEVEL) + add_executable(${PROJECT_NAME}) + + # Add key executable block + target_sources(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/dev/VisualStudio/main.c + ${CMAKE_CURRENT_LIST_DIR}/examples/test_code.c + ) + + target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/dev/VisualStudio + ) + + target_compile_definitions(${PROJECT_NAME} PUBLIC + WIN32 + _DEBUG + CONSOLE + LWGPS_DEV + ) + + # Add subdir with lwgps and link to project + add_subdirectory("lwgps" lwgps) + target_link_libraries(${PROJECT_NAME} lwgps) +else() + message("LWGPS: For library link, use CMakeLists.txt in /lwgps directory") +endif() \ No newline at end of file diff --git a/lwgps/CMakeLists.txt b/lwgps/CMakeLists.txt index febd4f0..f90a3f4 100644 --- a/lwgps/CMakeLists.txt +++ b/lwgps/CMakeLists.txt @@ -1 +1,20 @@ -add_subdirectory(src) +cmake_minimum_required(VERSION 3.13) + +# Debug message +message("LWGPS: Entering lib source CMakeLists.txt") + +# Set library name +set(LWGPS_LIB_NAME "lwgps") + +# Register library to the system +add_library(${LWGPS_LIB_NAME} INTERFACE) + +# Setup generic source files +target_sources(${LWGPS_LIB_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/src/lwgps/lwgps.c + ) + +# Setup include directories +target_include_directories(${LWGPS_LIB_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/src/include + ) From a8a47fe9e907d6541495745ce4e9959b53865387 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 24 Dec 2021 15:20:53 +0100 Subject: [PATCH 26/80] Change CMakelists to compile as standalone project or library --- .vscode/launch.json | 2 +- .vscode/tasks.json | 2 +- CMakeLists.txt | 59 ++++++++++++++++++++++++--------------------- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 5a04de8..8b95413 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "name": "(Windows) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}\\build\\LwGPS.exe", + "program": "${workspaceFolder}\\build\\LwLibPROJECT.exe", "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", "args": [], "stopAtEntry": false, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6d1726e..309d100 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -46,7 +46,7 @@ { "type": "shell", "label": "Run application", - "command": "${workspaceFolder}\\build\\LwGPS.exe", + "command": "${workspaceFolder}\\build\\LwLibPROJECT.exe", "args": [], "problemMatcher": [], }, diff --git a/CMakeLists.txt b/CMakeLists.txt index 30fa9f0..a3eb8d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,35 +1,40 @@ cmake_minimum_required(VERSION 3.0.0) # Setup project -project(LwGPS VERSION 2.0.1) +project(LwLibPROJECT VERSION 2.0.1) -# ------------------------ -# Configuration used if cmake uses this as -# top-level project CMakeLists.txt file -# This is normally used for development purpose only -if (PROJECT_IS_TOP_LEVEL) - add_executable(${PROJECT_NAME}) +# ------------------------------------------------- +# This CMakeLists.txt is used only if it is a top-level file. +# Purpose of it is to be able to compile project in standalone way only +# +# When library sources are to be included in another project +# user shall use /lwmem/CMakeLists.txt instead +if (NOT PROJECT_IS_TOP_LEVEL) + message(FATAL_ERROR "This CMakeLists.txt can only be used as top-level. Use /lwgps/CMakeLists.txt for library include purpose") +endif() - # Add key executable block - target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/dev/VisualStudio/main.c - ${CMAKE_CURRENT_LIST_DIR}/examples/test_code.c - ) +# Set as executable +add_executable(${PROJECT_NAME}) - target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/dev/VisualStudio - ) +# Add key executable block +target_sources(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/dev/VisualStudio/main.c + ${CMAKE_CURRENT_LIST_DIR}/examples/test_code.c + ) - target_compile_definitions(${PROJECT_NAME} PUBLIC - WIN32 - _DEBUG - CONSOLE - LWGPS_DEV - ) +# Add key include paths +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/dev/VisualStudio + ) - # Add subdir with lwgps and link to project - add_subdirectory("lwgps" lwgps) - target_link_libraries(${PROJECT_NAME} lwgps) -else() - message("LWGPS: For library link, use CMakeLists.txt in /lwgps directory") -endif() \ No newline at end of file +# Compilation definition information +target_compile_definitions(${PROJECT_NAME} PUBLIC + WIN32 + _DEBUG + CONSOLE + LWGPS_DEV + ) + +# Add subdir with lwgps and link to project +add_subdirectory("lwgps" lwgps) +target_link_libraries(${PROJECT_NAME} lwgps) \ No newline at end of file From 8eadd0b29583b2a3afdc2c7c7708227f51dae0c9 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 24 Dec 2021 18:57:03 +0100 Subject: [PATCH 27/80] Update CMake and split development and library --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a3eb8d8..7d44fc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,14 @@ cmake_minimum_required(VERSION 3.0.0) # Setup project -project(LwLibPROJECT VERSION 2.0.1) +project(LwLibPROJECT) # ------------------------------------------------- # This CMakeLists.txt is used only if it is a top-level file. # Purpose of it is to be able to compile project in standalone way only # # When library sources are to be included in another project -# user shall use /lwmem/CMakeLists.txt instead +# user shall use /lwgps/CMakeLists.txt instead if (NOT PROJECT_IS_TOP_LEVEL) message(FATAL_ERROR "This CMakeLists.txt can only be used as top-level. Use /lwgps/CMakeLists.txt for library include purpose") endif() From 9ce06a9b785eb1847a3335b2a1d72f5f6a007156 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 24 Dec 2021 19:44:26 +0100 Subject: [PATCH 28/80] Move dvp one folder up and update CMakeLists.txt --- CMakeLists.txt | 4 ++-- dev/{VisualStudio => }/lwgps_dev.sln | 0 dev/{VisualStudio => }/lwgps_dev.vcxproj | 6 +++--- dev/{VisualStudio => }/lwgps_dev.vcxproj.filters | 4 ++-- dev/{VisualStudio => }/lwgps_opts.h | 0 dev/{VisualStudio => }/main.c | 0 6 files changed, 7 insertions(+), 7 deletions(-) rename dev/{VisualStudio => }/lwgps_dev.sln (100%) rename dev/{VisualStudio => }/lwgps_dev.vcxproj (97%) rename dev/{VisualStudio => }/lwgps_dev.vcxproj.filters (87%) rename dev/{VisualStudio => }/lwgps_opts.h (100%) rename dev/{VisualStudio => }/main.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d44fc7..28b1350 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,13 +18,13 @@ add_executable(${PROJECT_NAME}) # Add key executable block target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/dev/VisualStudio/main.c + ${CMAKE_CURRENT_LIST_DIR}/dev/main.c ${CMAKE_CURRENT_LIST_DIR}/examples/test_code.c ) # Add key include paths target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/dev/VisualStudio + ${CMAKE_CURRENT_LIST_DIR}/dev ) # Compilation definition information diff --git a/dev/VisualStudio/lwgps_dev.sln b/dev/lwgps_dev.sln similarity index 100% rename from dev/VisualStudio/lwgps_dev.sln rename to dev/lwgps_dev.sln diff --git a/dev/VisualStudio/lwgps_dev.vcxproj b/dev/lwgps_dev.vcxproj similarity index 97% rename from dev/VisualStudio/lwgps_dev.vcxproj rename to dev/lwgps_dev.vcxproj index e1be4bf..1fd1c6b 100644 --- a/dev/VisualStudio/lwgps_dev.vcxproj +++ b/dev/lwgps_dev.vcxproj @@ -72,7 +72,7 @@ true - .;..\..\lwgps\src\include;$(IncludePath) + .;..\lwgps\src\include;$(IncludePath) true @@ -139,8 +139,8 @@ - - + + diff --git a/dev/VisualStudio/lwgps_dev.vcxproj.filters b/dev/lwgps_dev.vcxproj.filters similarity index 87% rename from dev/VisualStudio/lwgps_dev.vcxproj.filters rename to dev/lwgps_dev.vcxproj.filters index 5dd19f9..94d08aa 100644 --- a/dev/VisualStudio/lwgps_dev.vcxproj.filters +++ b/dev/lwgps_dev.vcxproj.filters @@ -10,13 +10,13 @@ - + Source Files\LwGPS Source Files - + Source Files diff --git a/dev/VisualStudio/lwgps_opts.h b/dev/lwgps_opts.h similarity index 100% rename from dev/VisualStudio/lwgps_opts.h rename to dev/lwgps_opts.h diff --git a/dev/VisualStudio/main.c b/dev/main.c similarity index 100% rename from dev/VisualStudio/main.c rename to dev/main.c From 15d452aea29807c0d25300d4fd3db2b81ccd5d04 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 24 Dec 2021 19:58:28 +0100 Subject: [PATCH 29/80] Update Changelog file for CMakeLists --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19d06c8..3750cee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Develop + +- Split CMakeLists.txt files between library and executable + ## v2.1.0 - Add configuration settings to be consistend with other LwXX libraries From 0ee86907b99c9280edf46f833f6222240ae6f03b Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 24 Dec 2021 20:11:18 +0100 Subject: [PATCH 30/80] Update getting started --- docs/get-started/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index 7e3c670..843981a 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -45,10 +45,10 @@ This is used when you do not have yet local copy on your machine. Update cloned to latest version """"""""""""""""""""""""""""""" -* Open console and navigate to path in the system where your resources repository is. Use command ``cd your_path`` -* Run ``git pull origin master --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``master`` branch -* Run ``git pull origin develop --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``develop`` branch -* Run ``git submodule foreach git pull origin master`` to update & merge all submodules +* Open console and navigate to path in the system where your repository is located. Use command ``cd your_path`` +* Run ``git pull origin master`` command to get latest changes on ``master`` branch +* Run ``git pull origin develop`` command to get latest changes on ``develop`` branch +* Run ``git submodule update --init --remote`` to update submodules to latest version .. note:: This is preferred option to use when you want to evaluate library and run prepared examples. From 683dc28c1c6fad23aafd1197dd61405d0687436d Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 27 Dec 2021 17:50:19 +0100 Subject: [PATCH 31/80] Update CMakeLists.txt for each library and split core and optional modules --- .vscode/c_cpp_properties.json | 2 +- lwgps/CMakeLists.txt | 20 ++++++-------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 7caebce..9d2a415 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,7 +4,7 @@ { "name": "Win32", "includePath": [ - "${workspaceFolder}\\dev\\VisualStudio\\", + "${workspaceFolder}\\dev\\", "${workspaceFolder}\\lwgps\\src\\include\\" ], "defines": [ diff --git a/lwgps/CMakeLists.txt b/lwgps/CMakeLists.txt index f90a3f4..42a4dd1 100644 --- a/lwgps/CMakeLists.txt +++ b/lwgps/CMakeLists.txt @@ -1,20 +1,12 @@ cmake_minimum_required(VERSION 3.13) # Debug message -message("LWGPS: Entering lib source CMakeLists.txt") - -# Set library name -set(LWGPS_LIB_NAME "lwgps") +message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") # Register library to the system -add_library(${LWGPS_LIB_NAME} INTERFACE) - -# Setup generic source files -target_sources(${LWGPS_LIB_NAME} INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/src/lwgps/lwgps.c - ) +add_library(lwgps INTERFACE) +target_sources(lwgps INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/lwgps/lwgps.c) +target_include_directories(lwgps INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include) -# Setup include directories -target_include_directories(${LWGPS_LIB_NAME} INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/src/include - ) +# Debug message +message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") From 9594af5aafc4bc96d2e98788f282cd3579c4b98c Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Thu, 13 Jan 2022 20:56:28 +0100 Subject: [PATCH 32/80] Update library.json --- library.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library.json b/library.json index 4b84e06..10f5ab2 100644 --- a/library.json +++ b/library.json @@ -9,9 +9,9 @@ }, "authors": [ { - "name": "Tilen Majerle", - "email": "tilen@majerle.eu", - "url": "https://majerle.eu" + "name": "Tilen Majerle", + "email": "tilen@majerle.eu", + "url": "https://majerle.eu" } ], "license": "MIT", @@ -28,7 +28,8 @@ "docs", "**/.vs", "**/Debug", - "build" + "build", + "**/build" ] } } \ No newline at end of file From 25dff836a6ae6898fa4f39ca42dd1ad78de77fb2 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 14 Jan 2022 23:07:43 +0100 Subject: [PATCH 33/80] Update license year to 2022 --- CHANGELOG.md | 1 + LICENSE | 2 +- dev/lwgps_opts.h | 2 +- lwgps/src/include/lwgps/lwgps.h | 2 +- lwgps/src/include/lwgps/lwgps_opt.h | 2 +- lwgps/src/include/lwgps/lwgps_opts_template.h | 2 +- lwgps/src/lwgps/lwgps.c | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3750cee..dc04c86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Develop - Split CMakeLists.txt files between library and executable +- Change license year to 2022 ## v2.1.0 diff --git a/LICENSE b/LICENSE index aa60317..5625f63 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Tilen MAJERLE +Copyright (c) 2022 Tilen MAJERLE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/dev/lwgps_opts.h b/dev/lwgps_opts.h index 1abd010..0302114 100644 --- a/dev/lwgps_opts.h +++ b/dev/lwgps_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2022 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/lwgps/src/include/lwgps/lwgps.h b/lwgps/src/include/lwgps/lwgps.h index 31c36c5..0578e8d 100644 --- a/lwgps/src/include/lwgps/lwgps.h +++ b/lwgps/src/include/lwgps/lwgps.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2022 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index a86a35f..8c07945 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2022 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/lwgps/src/include/lwgps/lwgps_opts_template.h b/lwgps/src/include/lwgps/lwgps_opts_template.h index 20632d6..05b2eed 100644 --- a/lwgps/src/include/lwgps/lwgps_opts_template.h +++ b/lwgps/src/include/lwgps/lwgps_opts_template.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2022 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index 195d47d..12bfda1 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2022 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation From 4f3d28a8ff3dc4179938d45089ba22caa13cf5f9 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 15 Jan 2022 00:41:45 +0100 Subject: [PATCH 34/80] Update .vscode files --- .vscode/extensions.json | 7 +++++++ .vscode/tasks.json | 12 ++---------- 2 files changed, 9 insertions(+), 10 deletions(-) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..6a07920 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools", + "twxs.cmake", + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 309d100..a4527df 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,19 +1,11 @@ { "version": "2.0.0", - - /* For this builds, you need - * - * - Ninja build system - * - MSYS2 compiler with ninja support - * - C/C++ extension for VSCode - * - CMake-Tools extension for VSCode - */ "tasks": [ { "type": "cppbuild", "label": "Build project", "command": "cmake", - "args": ["--build", "\"build\""], + "args": ["--build", "\"build\"", "-j", "8"], "options": { "cwd": "${workspaceFolder}" }, @@ -27,7 +19,7 @@ "type": "shell", "label": "Re-build project", "command": "cmake", - "args": ["--build", "\"build\"", "--clean-first", "-v"], + "args": ["--build", "\"build\"", "--clean-first", "-v", "-j", "8"], "options": { "cwd": "${workspaceFolder}" }, From 45e76615a7847c342e2b5820c7778a2564849d4f Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Tue, 18 Jan 2022 22:35:33 +0100 Subject: [PATCH 35/80] Update CMakeLists.txt to v3.22 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28b1350..aa10333 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.0) +cmake_minimum_required(VERSION 3.22) # Setup project project(LwLibPROJECT) From fe308eb33861800aa33189381d659f65f25bf75c Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Tue, 18 Jan 2022 22:40:28 +0100 Subject: [PATCH 36/80] Update CMakeLists.txt to v3.22 --- lwgps/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lwgps/CMakeLists.txt b/lwgps/CMakeLists.txt index 42a4dd1..394b180 100644 --- a/lwgps/CMakeLists.txt +++ b/lwgps/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.22) # Debug message message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") From 896d948e48aaaf566059c0ce5fba3e8e50267a76 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 6 Feb 2022 22:35:36 +0100 Subject: [PATCH 37/80] Update link to font-awesome and license to 2022 --- docs/conf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index f975ed0..c1ffd51 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ # -- Project information ----------------------------------------------------- project = 'LwGPS' -copyright = '2020, Tilen MAJERLE' +copyright = '2022, Tilen MAJERLE' author = 'Tilen MAJERLE' # Try to get branch at which this is running @@ -115,9 +115,10 @@ html_css_files = [ 'css/common.css', 'css/custom.css', + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css', ] html_js_files = [ - 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css' + '' ] master_doc = 'index' From df8acaa37822f6189049f0d8c9a438010c45a18a Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Wed, 16 Feb 2022 20:19:28 +0100 Subject: [PATCH 38/80] Update master branch to main --- docs/get-started/index.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index 843981a..24d7e8f 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -13,10 +13,10 @@ Download library Library is primarly hosted on `Github `_. -You can get it with: +You can get it by: * Downloading latest release from `releases area `_ on Github -* Cloning ``master`` branch for latest stable version +* Cloning ``main`` branch for latest stable version * Cloning ``develop`` branch for latest development Download from releases @@ -34,11 +34,11 @@ This is used when you do not have yet local copy on your machine. * Make sure ``git`` is installed. * Open console and navigate to path in the system to clone repository to. Use command ``cd your_path`` -* Clone repository with one of available ``3`` options +* Clone repository with one of available options below * Run ``git clone --recurse-submodules https://github.com/MaJerle/lwgps`` command to clone entire repository, including submodules * Run ``git clone --recurse-submodules --branch develop https://github.com/MaJerle/lwgps`` to clone `development` branch, including submodules - * Run ``git clone --recurse-submodules --branch master https://github.com/MaJerle/lwgps`` to clone `latest stable` branch, including submodules + * Run ``git clone --recurse-submodules --branch main https://github.com/MaJerle/lwgps`` to clone `latest stable` branch, including submodules * Navigate to ``examples`` directory and run favourite example @@ -46,7 +46,7 @@ Update cloned to latest version """"""""""""""""""""""""""""""" * Open console and navigate to path in the system where your repository is located. Use command ``cd your_path`` -* Run ``git pull origin master`` command to get latest changes on ``master`` branch +* Run ``git pull origin main`` command to get latest changes on ``main`` branch * Run ``git pull origin develop`` command to get latest changes on ``develop`` branch * Run ``git submodule update --init --remote`` to update submodules to latest version From dfd6a2e6e9b8fe3735428b33511711fbd10fcd1d Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 19 Feb 2022 00:14:53 +0100 Subject: [PATCH 39/80] Update requirements file for latest rtd theme --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index eb5e0fd..834b1bb 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,7 +2,7 @@ breathe>=4.9.1 colorama docutils==0.16 sphinx>=3.5.1 -sphinx_rtd_theme +sphinx_rtd_theme>=1.0.0 sphinx-tabs sphinxcontrib-svg2pdfconverter sphinx-sitemap From 18500f65e9e67205b9e4e917424b3da27bece8eb Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 19 Feb 2022 01:47:05 +0100 Subject: [PATCH 40/80] Update requirements file for latest rtd theme --- docs/conf.py | 10 +- docs/index.rst | 31 +- docs/static/dark-light/checked.svg | 1 + docs/static/dark-light/common-dark-light.css | 143 ++++++++ docs/static/dark-light/dark-mode-toggle.mjs | 329 +++++++++++++++++++ docs/static/dark-light/dark.css | 36 ++ docs/static/dark-light/light.css | 24 ++ docs/static/dark-light/moon.png | Bin 0 -> 3511 bytes docs/static/dark-light/moon.svg | 7 + docs/static/dark-light/sun.png | Bin 0 -> 1897 bytes docs/static/dark-light/sun.svg | 5 + docs/static/dark-light/unchecked.svg | 1 + 12 files changed, 575 insertions(+), 12 deletions(-) create mode 100644 docs/static/dark-light/checked.svg create mode 100644 docs/static/dark-light/common-dark-light.css create mode 100644 docs/static/dark-light/dark-mode-toggle.mjs create mode 100644 docs/static/dark-light/dark.css create mode 100644 docs/static/dark-light/light.css create mode 100644 docs/static/dark-light/moon.png create mode 100644 docs/static/dark-light/moon.svg create mode 100644 docs/static/dark-light/sun.png create mode 100644 docs/static/dark-light/sun.svg create mode 100644 docs/static/dark-light/unchecked.svg diff --git a/docs/conf.py b/docs/conf.py index c1ffd51..6fda2a6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -121,15 +121,13 @@ '' ] +# Master index file master_doc = 'index' -# -# Breathe configuration -# -# -# +# --- Breathe configuration ----------------------------------------------------- breathe_projects = { "lwgps": "_build/xml/" } breathe_default_project = "lwgps" -breathe_default_members = ('members', 'undoc-members') \ No newline at end of file +breathe_default_members = ('members', 'undoc-members') +breathe_show_enumvalue_initializer = True \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index a792a0b..145643c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -61,11 +61,30 @@ Table of contents ^^^^^^^^^^^^^^^^^ .. toctree:: - :maxdepth: 2 + :maxdepth: 2 + :caption: Contents - self - get-started/index - user-manual/index - api-reference/index - examples/index + self + get-started/index + user-manual/index + api-reference/index + examples/index + +.. toctree:: + :maxdepth: 2 + :caption: Other projects + :hidden: + + LwDTC - DateTimeCron + LwESP - ESP-AT library + LwGPS - GPS NMEA parser + LwGSM - GSM-AT library + LwJSON - JSON parser + LwMEM - Memory manager + LwOW - OneWire with UART + LwPKT - Packet protocol + LwPRINTF - Printf + LwRB - Ring buffer + LwSHELL - Shell + LwUTIL - Utility functions diff --git a/docs/static/dark-light/checked.svg b/docs/static/dark-light/checked.svg new file mode 100644 index 0000000..a78af82 --- /dev/null +++ b/docs/static/dark-light/checked.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/static/dark-light/common-dark-light.css b/docs/static/dark-light/common-dark-light.css new file mode 100644 index 0000000..9a2dc1d --- /dev/null +++ b/docs/static/dark-light/common-dark-light.css @@ -0,0 +1,143 @@ +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:root { + --heading-color: red; + --duration: 0.5s; + --timing: ease; +} + +*, +::before, +::after { + box-sizing: border-box; +} + +body { + margin: 0; + transition: + color var(--duration) var(--timing), + background-color var(--duration) var(--timing); + font-family: sans-serif; + font-size: 12pt; + background-color: var(--background-color); + color: var(--text-color); + display: flex; + justify-content: center; +} + +main { + margin: 1rem; + max-width: 30rem; + position: relative; +} + +h1 { + color: var(--heading-color); + text-shadow: 0.1rem 0.1rem 0.1rem var(--shadow-color); + transition: text-shadow var(--duration) var(--timing); +} + +img { + max-width: 100%; + height: auto; + transition: filter var(--duration) var(--timing); +} + +p { + line-height: 1.5; + word-wrap: break-word; + overflow-wrap: break-word; + hyphens: auto; +} + +fieldset { + border: solid 0.1rem; + box-shadow: 0.1rem 0.1rem 0.1rem var(--shadow-color); + transition: box-shadow var(--duration) var(--timing); +} + +div { + padding: 0.5rem; +} + +aside { + position: absolute; + right: 0; + padding: 0.5rem; +} + +aside:nth-of-type(1) { + top: 0; +} + +aside:nth-of-type(2) { + top: 3rem; +} + +aside:nth-of-type(3) { + top: 7rem; +} + +aside:nth-of-type(4) { + top: 12rem; +} + +#content select, +#content button, +#content input[type="text"], +#content input[type="search"] { + width: 15rem; +} + +dark-mode-toggle { + --dark-mode-toggle-remember-icon-checked: url("checked.svg"); + --dark-mode-toggle-remember-icon-unchecked: url("unchecked.svg"); + --dark-mode-toggle-remember-font: 0.75rem "Helvetica"; + --dark-mode-toggle-legend-font: bold 0.85rem "Helvetica"; + --dark-mode-toggle-label-font: 0.85rem "Helvetica"; + --dark-mode-toggle-color: var(--text-color); + --dark-mode-toggle-background-color: none; + + margin-bottom: 1.5rem; +} + +#dark-mode-toggle-1 { + --dark-mode-toggle-dark-icon: url("sun.png"); + --dark-mode-toggle-light-icon: url("moon.png"); +} + +#dark-mode-toggle-2 { + --dark-mode-toggle-dark-icon: url("sun.svg"); + --dark-mode-toggle-light-icon: url("moon.svg"); + --dark-mode-toggle-icon-size: 2rem; + --dark-mode-toggle-icon-filter: invert(100%); +} + +#dark-mode-toggle-3, +#dark-mode-toggle-4 { + --dark-mode-toggle-dark-icon: url("moon.png"); + --dark-mode-toggle-light-icon: url("sun.png"); +} + +#dark-mode-toggle-3 { + --dark-mode-toggle-remember-filter: invert(100%); +} + +#dark-mode-toggle-4 { + --dark-mode-toggle-active-mode-background-color: var(--accent-color); + --dark-mode-toggle-remember-filter: invert(100%); +} diff --git a/docs/static/dark-light/dark-mode-toggle.mjs b/docs/static/dark-light/dark-mode-toggle.mjs new file mode 100644 index 0000000..da22262 --- /dev/null +++ b/docs/static/dark-light/dark-mode-toggle.mjs @@ -0,0 +1,329 @@ +/** + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @license Š 2019 Google LLC. Licensed under the Apache License, Version 2.0. +const doc = document; +const store = localStorage; +const PREFERS_COLOR_SCHEME = 'prefers-color-scheme'; +const MEDIA = 'media'; +const LIGHT = 'light'; +const DARK = 'dark'; +const MQ_DARK = `(${PREFERS_COLOR_SCHEME}:${DARK})`; +const MQ_LIGHT = `(${PREFERS_COLOR_SCHEME}:${LIGHT})`; +const LINK_REL_STYLESHEET = 'link[rel=stylesheet]'; +const REMEMBER = 'remember'; +const LEGEND = 'legend'; +const TOGGLE = 'toggle'; +const SWITCH = 'switch'; +const APPEARANCE = 'appearance'; +const PERMANENT = 'permanent'; +const MODE = 'mode'; +const COLOR_SCHEME_CHANGE = 'colorschemechange'; +const PERMANENT_COLOR_SCHEME = 'permanentcolorscheme'; +const ALL = 'all'; +const NOT_ALL = 'not all'; +const NAME = 'dark-mode-toggle'; +const DEFAULT_URL = 'https://googlechromelabs.github.io/dark-mode-toggle/demo/'; + +// See https://html.spec.whatwg.org/multipage/common-dom-interfaces.html â†ĩ +// #reflecting-content-attributes-in-idl-attributes. +const installStringReflection = (obj, attrName, propName = attrName) => { + Object.defineProperty(obj, propName, { + enumerable: true, + get() { + const value = this.getAttribute(attrName); + return value === null ? '' : value; + }, + set(v) { + this.setAttribute(attrName, v); + }, + }); +}; + +const installBoolReflection = (obj, attrName, propName = attrName) => { + Object.defineProperty(obj, propName, { + enumerable: true, + get() { + return this.hasAttribute(attrName); + }, + set(v) { + if (v) { + this.setAttribute(attrName, ''); + } else { + this.removeAttribute(attrName); + } + }, + }); +}; + +const template = doc.createElement('template'); +// ⚠ī¸ Note: this is a minified version of `src/template-contents.tpl`. +// Compress the CSS with https://cssminifier.com/, then paste it here. +// eslint-disable-next-line max-len +template.innerHTML = `
`; + +export class DarkModeToggle extends HTMLElement { + static get observedAttributes() { + return [MODE, APPEARANCE, PERMANENT, LEGEND, LIGHT, DARK, REMEMBER]; + } + + constructor() { + super(); + + installStringReflection(this, MODE); + installStringReflection(this, APPEARANCE); + installStringReflection(this, LEGEND); + installStringReflection(this, LIGHT); + installStringReflection(this, DARK); + installStringReflection(this, REMEMBER); + + installBoolReflection(this, PERMANENT); + + this._darkCSS = null; + this._lightCSS = null; + + doc.addEventListener(COLOR_SCHEME_CHANGE, (event) => { + this.mode = event.detail.colorScheme; + this._updateRadios(); + this._updateCheckbox(); + }); + + doc.addEventListener(PERMANENT_COLOR_SCHEME, (event) => { + this.permanent = event.detail.permanent; + this._permanentCheckbox.checked = this.permanent; + }); + + this._initializeDOM(); + } + + _initializeDOM() { + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.appendChild(template.content.cloneNode(true)); + + // We need to support `media="(prefers-color-scheme: dark)"` (with space) + // and `media="(prefers-color-scheme:dark)"` (without space) + this._darkCSS = doc.querySelectorAll(`${LINK_REL_STYLESHEET}[${MEDIA}*=${PREFERS_COLOR_SCHEME}][${MEDIA}*="${DARK}"]`); + this._lightCSS = doc.querySelectorAll(`${LINK_REL_STYLESHEET}[${MEDIA}*=${PREFERS_COLOR_SCHEME}][${MEDIA}*="${LIGHT}"]`); + + // Get DOM references. + this._lightRadio = shadowRoot.querySelector('[part=lightRadio]'); + this._lightLabel = shadowRoot.querySelector('[part=lightLabel]'); + this._darkRadio = shadowRoot.querySelector('[part=darkRadio]'); + this._darkLabel = shadowRoot.querySelector('[part=darkLabel]'); + this._darkCheckbox = shadowRoot.querySelector('[part=toggleCheckbox]'); + this._checkboxLabel = shadowRoot.querySelector('[part=toggleLabel]'); + this._legendLabel = shadowRoot.querySelector('legend'); + this._permanentAside = shadowRoot.querySelector('aside'); + this._permanentCheckbox = + shadowRoot.querySelector('[part=permanentCheckbox]'); + this._permanentLabel = shadowRoot.querySelector('[part=permanentLabel]'); + + // Does the browser support native `prefers-color-scheme`? + const hasNativePrefersColorScheme = + matchMedia(MQ_DARK).media !== NOT_ALL; + // Listen to `prefers-color-scheme` changes. + if (hasNativePrefersColorScheme) { + matchMedia(MQ_DARK).addListener(({matches}) => { + this.mode = matches ? DARK : LIGHT; + this._dispatchEvent(COLOR_SCHEME_CHANGE, {colorScheme: this.mode}); + }); + } + // Set initial state, giving preference to a remembered value, then the + // native value (if supported), and eventually defaulting to a light + // experience. + const rememberedValue = store.getItem(NAME); + if (rememberedValue && [DARK, LIGHT].includes(rememberedValue)) { + this.mode = rememberedValue; + this._permanentCheckbox.checked = true; + this.permanent = true; + } else if (hasNativePrefersColorScheme) { + this.mode = matchMedia(MQ_LIGHT).matches ? LIGHT : DARK; + } + if (!this.mode) { + this.mode = LIGHT; + } + if (this.permanent && !rememberedValue) { + store.setItem(NAME, this.mode); + } + + // Default to toggle appearance. + if (!this.appearance) { + this.appearance = TOGGLE; + } + + // Update the appearance to either of toggle or switch. + this._updateAppearance(); + + // Update the radios + this._updateRadios(); + + // Make the checkbox reflect the state of the radios + this._updateCheckbox(); + + // Synchronize the behavior of the radio and the checkbox. + [this._lightRadio, this._darkRadio].forEach((input) => { + input.addEventListener('change', () => { + this.mode = this._lightRadio.checked ? LIGHT : DARK; + this._updateCheckbox(); + this._dispatchEvent(COLOR_SCHEME_CHANGE, {colorScheme: this.mode}); + }); + }); + this._darkCheckbox.addEventListener('change', () => { + this.mode = this._darkCheckbox.checked ? DARK : LIGHT; + this._updateRadios(); + this._dispatchEvent(COLOR_SCHEME_CHANGE, {colorScheme: this.mode}); + }); + + // Make remembering the last mode optional + this._permanentCheckbox.addEventListener('change', () => { + this.permanent = this._permanentCheckbox.checked; + this._dispatchEvent(PERMANENT_COLOR_SCHEME, { + permanent: this.permanent, + }); + }); + + // Finally update the mode and let the world know what's going on + this._updateMode(); + this._dispatchEvent(COLOR_SCHEME_CHANGE, {colorScheme: this.mode}); + this._dispatchEvent(PERMANENT_COLOR_SCHEME, { + permanent: this.permanent, + }); + } + + attributeChangedCallback(name, oldValue, newValue) { + if (name === MODE) { + if (![LIGHT, DARK].includes(newValue)) { + throw new RangeError(`Allowed values: "${LIGHT}" and "${DARK}".`); + } + // Only show the dialog programmatically on devices not capable of hover + // and only if there is a label + if (matchMedia('(hover:none)').matches && this.remember) { + this._showPermanentAside(); + } + if (this.permanent) { + store.setItem(NAME, this.mode); + } + this._updateRadios(); + this._updateCheckbox(); + this._updateMode(); + } else if (name === APPEARANCE) { + if (![TOGGLE, SWITCH].includes(newValue)) { + throw new RangeError(`Allowed values: "${TOGGLE}" and "${SWITCH}".`); + } + this._updateAppearance(); + } else if (name === PERMANENT) { + if (this.permanent) { + store.setItem(NAME, this.mode); + } else { + store.removeItem(NAME); + } + this._permanentCheckbox.checked = this.permanent; + } else if (name === LEGEND) { + this._legendLabel.textContent = newValue; + } else if (name === REMEMBER) { + this._permanentLabel.textContent = newValue; + } else if (name === LIGHT) { + this._lightLabel.textContent = newValue; + if (this.mode === LIGHT) { + this._checkboxLabel.textContent = newValue; + } + } else if (name === DARK) { + this._darkLabel.textContent = newValue; + if (this.mode === DARK) { + this._checkboxLabel.textContent = newValue; + } + } + } + + _dispatchEvent(type, value) { + this.dispatchEvent(new CustomEvent(type, { + bubbles: true, + composed: true, + detail: value, + })); + } + + _updateAppearance() { + // Hide or show the light-related affordances dependent on the appearance, + // which can be "switch" or "toggle". + const appearAsToggle = this.appearance === TOGGLE; + this._lightRadio.hidden = appearAsToggle; + this._lightLabel.hidden = appearAsToggle; + this._darkRadio.hidden = appearAsToggle; + this._darkLabel.hidden = appearAsToggle; + this._darkCheckbox.hidden = !appearAsToggle; + this._checkboxLabel.hidden = !appearAsToggle; + } + + _updateRadios() { + if (this.mode === LIGHT) { + this._lightRadio.checked = true; + } else { + this._darkRadio.checked = true; + } + } + + _updateCheckbox() { + if (this.mode === LIGHT) { + this._checkboxLabel.style.setProperty(`--${NAME}-checkbox-icon`, + `var(--${NAME}-light-icon,url("${DEFAULT_URL}moon.png"))`); + this._checkboxLabel.textContent = this.light; + if (!this.light) { + this._checkboxLabel.ariaLabel = DARK; + } + this._darkCheckbox.checked = false; + } else { + this._checkboxLabel.style.setProperty(`--${NAME}-checkbox-icon`, + `var(--${NAME}-dark-icon,url("${DEFAULT_URL}sun.png"))`); + this._checkboxLabel.textContent = this.dark; + if (!this.dark) { + this._checkboxLabel.ariaLabel = LIGHT; + } + this._darkCheckbox.checked = true; + } + } + + _updateMode() { + if (this.mode === LIGHT) { + this._lightCSS.forEach((link) => { + link.media = ALL; + link.disabled = false; + }); + this._darkCSS.forEach((link) => { + link.media = NOT_ALL; + link.disabled = true; + }); + } else { + this._darkCSS.forEach((link) => { + link.media = ALL; + link.disabled = false; + }); + this._lightCSS.forEach((link) => { + link.media = NOT_ALL; + link.disabled = true; + }); + } + } + + _showPermanentAside() { + this._permanentAside.style.visibility = 'visible'; + setTimeout(() => { + this._permanentAside.style.visibility = 'hidden'; + }, 3000); + } +} + +customElements.define(NAME, DarkModeToggle); \ No newline at end of file diff --git a/docs/static/dark-light/dark.css b/docs/static/dark-light/dark.css new file mode 100644 index 0000000..6ed8cfb --- /dev/null +++ b/docs/static/dark-light/dark.css @@ -0,0 +1,36 @@ +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:root { + color-scheme: dark; /* stylelint-disable-line property-no-unknown */ + + --background-color: rgb(15 15 15); + --text-color: rgb(240 240 240); + --shadow-color: rgb(240 240 240 / 50%); + --accent-color: rgb(0 0 240 / 50%); +} + +img { + filter: grayscale(50%); +} + +.icon { + filter: invert(100%); +} + +a { + color: yellow; +} diff --git a/docs/static/dark-light/light.css b/docs/static/dark-light/light.css new file mode 100644 index 0000000..f73cf7b --- /dev/null +++ b/docs/static/dark-light/light.css @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:root { + color-scheme: light; /* stylelint-disable-line property-no-unknown */ + + --background-color: rgb(240 240 240); + --text-color: rgb(15 15 15); + --shadow-color: rgb(15 15 15 / 50%); + --accent-color: rgb(240 0 0 / 50%); +} diff --git a/docs/static/dark-light/moon.png b/docs/static/dark-light/moon.png new file mode 100644 index 0000000000000000000000000000000000000000..0ad57d90044ef1f66d56d9208e6a6b3db43c7c55 GIT binary patch literal 3511 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 literal 0 HcmV?d00001 diff --git a/docs/static/dark-light/moon.svg b/docs/static/dark-light/moon.svg new file mode 100644 index 0000000..fad89a4 --- /dev/null +++ b/docs/static/dark-light/moon.svg @@ -0,0 +1,7 @@ + + + + moon + + + diff --git a/docs/static/dark-light/sun.png b/docs/static/dark-light/sun.png new file mode 100644 index 0000000000000000000000000000000000000000..40c9b362bd4efe10a77721de66ea94b12437db56 GIT binary patch literal 1897 zcmV-v2bTDWP)!ye&-ZTBt zRs7RL{nau3#6|zXE&seB|G6&zxe))dEB~|s|F0PTtpWe00{@`^LH*>T0000EbW%=J z00s~oFGyc_ny|y&@b)K_;4lCH2C7L!K~#9!?VF2k+d2$}>-$YP%bZ!JY1w)Iw>%WB zgvplJm0ToPv46#Y4Q)Ph=-R3Swh^8{TqUu9~k`lAeZFnad>@@<67%+9A6*g zRFS90Hv~Dio*v&2;ms>=!N0XZ8{*EdDqLK!Hl^`cYJXy;hcNsc~d90NnXIDiP=NMF#JJ93`a!>*bLYRFsu^$%@lx$?C@6 zX@f{aF}aLxg9`wJwdy@rmTakkxK@P5tG|&T52?)UvuxcYsYETWne>Krj;X1gtDMb-{62(6$%q&tE@D^tZ6vj=#;3M}Q^`FK__Nl{q_oyuHlun z+hk~4<}!Ah417}VR$;j(;ck*?KeNGmm1BDp?k1VTjOE9E72Q!By`g1ox5w@az;XRq zgT>@y`vtDf)$zy%3wM)zJnmmySwo%{gSW|xuiIUH-6+XQh0fE$-7uMbeZ(pah89($ z5W&M>2D{~jO_`^05ERe~S|5X*uTKOfsk+FL$On1=5^^acU>{$%ok0=+G!?-=2i00z ztT9{xbPQ%s`}n%EXCslV6nlLON`k&$YP>UpeL_rf;F;?IV|oBhQgxaC>2(KX5p*0~ zO}i9YKAx7exqxleH}t)>IdPM1U$K0r-Q31xmaAO-z*+?S}fp+!A^tzttk?xd3lZTuqVa>o}OBKxJ{>#tm?(^ zo#3{e1$+yAxUHikFKe}ItMCq!E|r};cbinpkW;EvtAEB7BK)S@U#jo1XLLYm2?_b`ZW8CuCQV+ z|9i{Zj}ih3`eHvfDp9UZpEVfsueeEsT-u8L;7p-GziVp8E$saU<9znKm?Nrm|Lqv@ z?A40srnA{&vb3gWZgP1wUl0%ZE^frFJ^yx-L8y~`D+_QYu-MFKmOvd=xM!Kogsv=W zu#gG8+ESEe<|HlDz=mQ!NfT9XHBqH~%dNeAE!1fiGPFl&8w=H8TR301Y_iINSC%G& z9ogN%)*9ttX5mf)Koy5R=5fOiH@*DKXkcbd+@aTjTPk+55GGGN3#p2{s1>nW)~RI? zw_C;}cQXl@vV}~4#))MBKvikPL*WJiz|DV7JpPfv5CWQsxib9;ns+gI08*Vta%|uw zmYgiGa+bx*m~9N3cgfJam)W9>?Pav+w6vyWYP_HWCVX;rU9eiqU{OxWyV2s^D7BW^ zqSh)4nX+Bx$JKA6>!d+3+2C*GM(k$RBRji_16G!snCJ0>7WVA)=jJ$k# zPp1)`HPoDZ87p`^QYGVXW00000NkvXXu0mjf*I}_| literal 0 HcmV?d00001 diff --git a/docs/static/dark-light/sun.svg b/docs/static/dark-light/sun.svg new file mode 100644 index 0000000..0b18941 --- /dev/null +++ b/docs/static/dark-light/sun.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/docs/static/dark-light/unchecked.svg b/docs/static/dark-light/unchecked.svg new file mode 100644 index 0000000..6702330 --- /dev/null +++ b/docs/static/dark-light/unchecked.svg @@ -0,0 +1 @@ + \ No newline at end of file From 7a3cd92bb7a94090416c947b33aba8d851779a2b Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 21 Feb 2022 19:14:11 +0100 Subject: [PATCH 41/80] docs: Mention VSCode support --- docs/conf.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 6fda2a6..ac5817e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,10 +28,20 @@ # Try to get branch at which this is running # and try to determine which version to display in sphinx -# Version is using git tag if on master or "latest-develop" if on develop branch +# Version is using git tag if on master/main or "latest-develop" if on develop branch version = '' git_branch = '' +def cmd_exec_print(t): + print("cmd > ", t, "\n", os.popen(t).read().strip(), "\n") + +# Print demo data here +cmd_exec_print('git branch') +cmd_exec_print('git describe') +cmd_exec_print('git describe --tags') +cmd_exec_print('git describe --tags --abbrev=0') +cmd_exec_print('git describe --tags --abbrev=1') + # Get current branch res = os.popen('git branch').read().strip() for line in res.split("\n"): @@ -41,17 +51,18 @@ # Decision for display version git_branch = git_branch.replace('(HEAD detached at ', '').replace(')', '') if git_branch.find('master') >= 0 or git_branch.find('main') >= 0: - version = os.popen('git describe --tags --abbrev=0').read().strip() - if version == '': - version = 'v0.0.0' -elif git_branch.find('develop') != -1 and not (git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0): + #version = os.popen('git describe --tags --abbrev=0').read().strip() + version = 'latest-stable' +elif git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0: + version = 'branch-' + git_branch +elif git_branch == 'develop' or git_branch == 'origin/develop': version = 'latest-develop' else: - version = 'branch-' + git_branch + version = os.popen('git describe --tags --abbrev=0').read().strip() # For debugging purpose only print("GIT BRANCH: " + git_branch) -print("GIT VERSION: " + version) +print("PROJ VERSION: " + version) # -- General configuration --------------------------------------------------- From 40f11fea1ad1f2b5124efa0610b532176cee69f1 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Tue, 22 Feb 2022 22:04:33 +0100 Subject: [PATCH 42/80] Update tasks.json to add docs commands --- .vscode/tasks.json | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a4527df..4a5e5eb 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -42,5 +42,32 @@ "args": [], "problemMatcher": [], }, + { + "label": "Docs: Install python plugins from requirements.txt file", + "type": "shell", + "command": "python -m pip install -r requirements.txt", + "options": { + "cwd": "${workspaceFolder}/docs" + }, + "problemMatcher": [] + }, + { + "label": "Docs: Generate html", + "type": "shell", + "command": ".\\make html", + "options": { + "cwd": "${workspaceFolder}/docs" + }, + "problemMatcher": [] + }, + { + "label": "Docs: Clean build directory", + "type": "shell", + "command": ".\\make clean", + "options": { + "cwd": "${workspaceFolder}/docs" + }, + "problemMatcher": [] + }, ] } \ No newline at end of file From 7c870dbe2822ffcb34231399383f22d623046852 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 4 Mar 2022 11:46:37 +0100 Subject: [PATCH 43/80] Add inner directive for doxygengroup --- docs/api-reference/gps_opt.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api-reference/gps_opt.rst b/docs/api-reference/gps_opt.rst index 87cc51d..9f8bb97 100644 --- a/docs/api-reference/gps_opt.rst +++ b/docs/api-reference/gps_opt.rst @@ -9,4 +9,5 @@ When any of the settings shall be modified, it shall be done in dedicated applic .. note:: Check :ref:`getting_started` to create configuration file. -.. doxygengroup:: LWGPS_OPT \ No newline at end of file +.. doxygengroup:: LWGPS_OPT + :inner: \ No newline at end of file From 6187ef51cfd8c25ae409fca6a5be0565555f1315 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Wed, 13 Apr 2022 14:58:29 +0200 Subject: [PATCH 44/80] Update vscode c_cpp_properties.json to use cmake as provider --- .vscode/c_cpp_properties.json | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 9d2a415..9768bc2 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,17 +3,6 @@ "configurations": [ { "name": "Win32", - "includePath": [ - "${workspaceFolder}\\dev\\", - "${workspaceFolder}\\lwgps\\src\\include\\" - ], - "defines": [ - "WIN32", - "_DEBUG", - "UNICODE", - "_UNICODE", - "LWGPS_DEV" - ], "compilerPath": "c:\\msys64\\mingw64\\bin\\gcc.exe", "cStandard": "gnu17", "cppStandard": "gnu++14", From 37649c71bc665d49f68c8890f368b9d0cddc1dad Mon Sep 17 00:00:00 2001 From: Sebastian Krebs Date: Tue, 26 Apr 2022 10:39:52 +0200 Subject: [PATCH 45/80] add CITATION.cff to support citation-function of GitHub --- CITATION.cff | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 CITATION.cff diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..35735fc --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,17 @@ +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! + +cff-version: 1.2.0 +title: lwgps +message: >- + If you use this software, please cite it using the + metadata from this file. +type: software +authors: + - family-names: Majerle + given-names: Tilen + email: tilen.majerle@gmail.com + - given-names: Sirio + family-names: Balmelli + - given-names: Robin + family-names: Mueller From 083213640afef2365e991d9f061241929d532215 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Tue, 10 May 2022 20:38:01 +0200 Subject: [PATCH 46/80] docs: Update index rst --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index 145643c..302fec3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -77,6 +77,7 @@ Table of contents LwDTC - DateTimeCron LwESP - ESP-AT library + LwEVT - Event manager LwGPS - GPS NMEA parser LwGSM - GSM-AT library LwJSON - JSON parser From 2cf00f834806e675cf84292fe01614787ca02645 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Wed, 18 May 2022 20:37:13 +0200 Subject: [PATCH 47/80] Update vscode & CMake related points --- .vscode/launch.json | 5 ++--- .vscode/settings.json | 10 ++++++++++ .vscode/tasks.json | 8 ++++---- cmake/i686-w64-mingw32-gcc.cmake | 7 +++++++ cmake/x86_64-w64-mingw32-gcc.cmake | 7 +++++++ 5 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 cmake/i686-w64-mingw32-gcc.cmake create mode 100644 cmake/x86_64-w64-mingw32-gcc.cmake diff --git a/.vscode/launch.json b/.vscode/launch.json index 8b95413..bf1450f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,13 +8,12 @@ "name": "(Windows) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}\\build\\LwLibPROJECT.exe", + "program": "${command:cmake.buildDirectory}\\LwLibPROJECT.exe", "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", - "environment": [], - "console": "integratedTerminal" + "environment": [] } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3b59a00 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "files.associations": { + "lwevt_types.h": "c", + "lwevt_type.h": "c", + "lwevt.h": "c", + "string.h": "c", + "lwevt_opt.h": "c" + }, + "esbonio.sphinx.confDir": "" +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4a5e5eb..103e43a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,7 +5,7 @@ "type": "cppbuild", "label": "Build project", "command": "cmake", - "args": ["--build", "\"build\"", "-j", "8"], + "args": ["--build", "${command:cmake.buildDirectory}", "-j", "8"], "options": { "cwd": "${workspaceFolder}" }, @@ -19,7 +19,7 @@ "type": "shell", "label": "Re-build project", "command": "cmake", - "args": ["--build", "\"build\"", "--clean-first", "-v", "-j", "8"], + "args": ["--build", "${command:cmake.buildDirectory}", "--clean-first", "-v", "-j", "8"], "options": { "cwd": "${workspaceFolder}" }, @@ -29,7 +29,7 @@ "type": "shell", "label": "Clean project", "command": "cmake", - "args": ["--build", "\"build\"", "--target", "clean"], + "args": ["--build", "${command:cmake.buildDirectory}", "--target", "clean"], "options": { "cwd": "${workspaceFolder}" }, @@ -38,7 +38,7 @@ { "type": "shell", "label": "Run application", - "command": "${workspaceFolder}\\build\\LwLibPROJECT.exe", + "command": "${command:cmake.buildDirectory}\\LwLibPROJECT.exe", "args": [], "problemMatcher": [], }, diff --git a/cmake/i686-w64-mingw32-gcc.cmake b/cmake/i686-w64-mingw32-gcc.cmake new file mode 100644 index 0000000..334d580 --- /dev/null +++ b/cmake/i686-w64-mingw32-gcc.cmake @@ -0,0 +1,7 @@ +set(CMAKE_SYSTEM_NAME Windows) + +# Some default GCC settings +set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) +set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) diff --git a/cmake/x86_64-w64-mingw32-gcc.cmake b/cmake/x86_64-w64-mingw32-gcc.cmake new file mode 100644 index 0000000..1d82433 --- /dev/null +++ b/cmake/x86_64-w64-mingw32-gcc.cmake @@ -0,0 +1,7 @@ +set(CMAKE_SYSTEM_NAME Windows) + +# Some default GCC settings +set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) +set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) From 99d63bb6fd760266be401e3d03dda69366d61ba6 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Wed, 18 May 2022 23:54:43 +0200 Subject: [PATCH 48/80] Update vscode & CMake related points --- .vscode/launch.json | 2 +- .vscode/tasks.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index bf1450f..a53089a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "name": "(Windows) Launch", "type": "cppdbg", "request": "launch", - "program": "${command:cmake.buildDirectory}\\LwLibPROJECT.exe", + "program": "${command:cmake.launchTargetPath}", "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", "args": [], "stopAtEntry": false, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 103e43a..b15064b 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -38,7 +38,7 @@ { "type": "shell", "label": "Run application", - "command": "${command:cmake.buildDirectory}\\LwLibPROJECT.exe", + "command": "${command:cmake.launchTargetPath}", "args": [], "problemMatcher": [], }, From 38ee8c8f1e29af9c20257ed9350cb2d912d85bd5 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Tue, 24 May 2022 10:10:15 +0200 Subject: [PATCH 49/80] Add CMake Presets --- CMakePresets.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 CMakePresets.json diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..7d277c4 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,30 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "Win32-Debug", + "inherits": "default", + "toolchainFile": "${sourceDir}/cmake/i686-w64-mingw32-gcc.cmake", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "Win64-Debug", + "inherits": "default", + "toolchainFile": "${sourceDir}/cmake/x86_64-w64-mingw32-gcc.cmake", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + } + ] +} \ No newline at end of file From 7e9e52910409a1b9efe02ce2b9194a41cbbad724 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Wed, 27 Jul 2022 11:56:22 +0200 Subject: [PATCH 50/80] Reduce compiler warnings for -Wall -Wpedantic -Wextra --- CMakeLists.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aa10333..8ec0d15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,12 +20,12 @@ add_executable(${PROJECT_NAME}) target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/dev/main.c ${CMAKE_CURRENT_LIST_DIR}/examples/test_code.c - ) +) # Add key include paths target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/dev - ) +) # Compilation definition information target_compile_definitions(${PROJECT_NAME} PUBLIC @@ -33,7 +33,14 @@ target_compile_definitions(${PROJECT_NAME} PUBLIC _DEBUG CONSOLE LWGPS_DEV - ) +) + +# Compiler options +target_compile_options(${PROJECT_NAME} PRIVATE + -Wall + -Wextra + -Wpedantic +) # Add subdir with lwgps and link to project add_subdirectory("lwgps" lwgps) From 0981700f97770a1e5190f5ad7cc03303acc0f729 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Wed, 17 Aug 2022 21:24:57 +0200 Subject: [PATCH 51/80] Update C/C++ properties --- .vscode/c_cpp_properties.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 9768bc2..4f457d1 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -2,11 +2,12 @@ "version": 4, "configurations": [ { + /* + * Full configuration is provided by CMake plugin for vscode, + * that shall be installed by user + */ "name": "Win32", - "compilerPath": "c:\\msys64\\mingw64\\bin\\gcc.exe", - "cStandard": "gnu17", - "cppStandard": "gnu++14", - "intelliSenseMode": "windows-gcc-x86", + "intelliSenseMode": "${default}", "configurationProvider": "ms-vscode.cmake-tools" } ] From e62ff81b9f92eee97c799d34508314081154b196 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 21 Aug 2022 16:50:07 +0200 Subject: [PATCH 52/80] Update docs --- docs/changelog/index.rst | 6 ++++++ docs/index.rst | 1 + 2 files changed, 7 insertions(+) create mode 100644 docs/changelog/index.rst diff --git a/docs/changelog/index.rst b/docs/changelog/index.rst new file mode 100644 index 0000000..51b89b4 --- /dev/null +++ b/docs/changelog/index.rst @@ -0,0 +1,6 @@ +.. _changelof: + +Changelog +========= + +.. literalinclude:: ../../CHANGELOG.md diff --git a/docs/index.rst b/docs/index.rst index 302fec3..9afa481 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -69,6 +69,7 @@ Table of contents user-manual/index api-reference/index examples/index + changelog/index .. toctree:: :maxdepth: 2 From 2dd94e5242705cdf634d7db1520dc9597cb90e04 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Tue, 30 Aug 2022 22:19:38 +0200 Subject: [PATCH 53/80] Add .clang-format first file --- .clang-format | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++ CHANGELOG.md | 1 + 2 files changed, 200 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..7f92b4a --- /dev/null +++ b/.clang-format @@ -0,0 +1,199 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Right +AlignOperands: Align +InsertBraces: true # Control statements must have curly brackets +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: AllDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: false +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Always +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +... + diff --git a/CHANGELOG.md b/CHANGELOG.md index dc04c86..1196c9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Split CMakeLists.txt files between library and executable - Change license year to 2022 +- Add `.clang-format` draft ## v2.1.0 From f7a4c951c23eac609bb8f6986f77bb96dcd4db2a Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Thu, 1 Sep 2022 19:05:39 +0200 Subject: [PATCH 54/80] Apply clang-format --- .clang-format | 18 +- lwgps/src/include/lwgps/lwgps.h | 251 ++++++++++++++-------------- lwgps/src/include/lwgps/lwgps_opt.h | 20 +-- lwgps/src/lwgps/lwgps.c | 218 ++++++++++++------------ 4 files changed, 255 insertions(+), 252 deletions(-) diff --git a/.clang-format b/.clang-format index 7f92b4a..490ba55 100644 --- a/.clang-format +++ b/.clang-format @@ -30,7 +30,7 @@ AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: AllDefinitions AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine +AlwaysBreakTemplateDeclarations: Yes AttributeMacros: - __capability BinPackArguments: true @@ -90,18 +90,12 @@ IfMacros: - KJ_IF_MAYBE IncludeBlocks: Preserve IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - SortPriority: 0 - CaseSensitive: false - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - SortPriority: 0 - CaseSensitive: false - - Regex: '.*' + - Regex: '^<(.*)>' + Priority: 0 + - Regex: '^"(.*)"' Priority: 1 - SortPriority: 0 - CaseSensitive: false + - Regex: '(.*)' + Priority: 2 IncludeIsMainRegex: '(Test)?$' IncludeIsMainSourceRegex: '' IndentAccessModifiers: false diff --git a/lwgps/src/include/lwgps/lwgps.h b/lwgps/src/include/lwgps/lwgps.h index 0578e8d..f6c91f8 100644 --- a/lwgps/src/include/lwgps/lwgps.h +++ b/lwgps/src/include/lwgps/lwgps.h @@ -34,9 +34,9 @@ #ifndef LWGPS_HDR_H #define LWGPS_HDR_H -#include -#include #include +#include +#include #include "lwgps/lwgps_opt.h" #ifdef __cplusplus @@ -63,24 +63,24 @@ typedef float lwgps_float_t; * \brief Satellite descriptor */ typedef struct { - uint8_t num; /*!< Satellite number */ - uint8_t elevation; /*!< Elevation value */ - uint16_t azimuth; /*!< Azimuth in degrees */ - uint8_t snr; /*!< Signal-to-noise ratio */ + uint8_t num; /*!< Satellite number */ + uint8_t elevation; /*!< Elevation value */ + uint16_t azimuth; /*!< Azimuth in degrees */ + uint8_t snr; /*!< Signal-to-noise ratio */ } lwgps_sat_t; /** * \brief ENUM of possible GPS statements parsed */ typedef enum { - STAT_UNKNOWN = 0, /*!< Unknown NMEA statement */ - STAT_GGA = 1, /*!< GPGGA statement */ - STAT_GSA = 2, /*!< GPGSA statement */ - STAT_GSV = 3, /*!< GPGSV statement */ - STAT_RMC = 4, /*!< GPRMC statement */ - STAT_UBX = 5, /*!< UBX statement (uBlox specific) */ - STAT_UBX_TIME = 6, /*!< UBX TIME statement (uBlox specific) */ - STAT_CHECKSUM_FAIL = UINT8_MAX /*!< Special case, used when checksum fails */ + STAT_UNKNOWN = 0, /*!< Unknown NMEA statement */ + STAT_GGA = 1, /*!< GPGGA statement */ + STAT_GSA = 2, /*!< GPGSA statement */ + STAT_GSV = 3, /*!< GPGSV statement */ + STAT_RMC = 4, /*!< GPRMC statement */ + STAT_UBX = 5, /*!< UBX statement (uBlox specific) */ + STAT_UBX_TIME = 6, /*!< UBX TIME statement (uBlox specific) */ + STAT_CHECKSUM_FAIL = UINT8_MAX /*!< Special case, used when checksum fails */ } lwgps_statement_t; /** @@ -89,29 +89,29 @@ typedef enum { typedef struct { #if LWGPS_CFG_STATEMENT_GPGGA || __DOXYGEN__ /* Information related to GPGGA statement */ - lwgps_float_t latitude; /*!< Latitude in units of degrees */ - lwgps_float_t longitude; /*!< Longitude in units of degrees */ - lwgps_float_t altitude; /*!< Altitude in units of meters */ - lwgps_float_t geo_sep; /*!< Geoid separation in units of meters */ - uint8_t sats_in_use; /*!< Number of satellites in use */ - uint8_t fix; /*!< Fix status. `0` = invalid, `1` = GPS fix, `2` = DGPS fix, `3` = PPS fix */ - uint8_t hours; /*!< Hours in UTC */ - uint8_t minutes; /*!< Minutes in UTC */ - uint8_t seconds; /*!< Seconds in UTC */ -#endif /* LWGPS_CFG_STATEMENT_GPGGA || __DOXYGEN__ */ + lwgps_float_t latitude; /*!< Latitude in units of degrees */ + lwgps_float_t longitude; /*!< Longitude in units of degrees */ + lwgps_float_t altitude; /*!< Altitude in units of meters */ + lwgps_float_t geo_sep; /*!< Geoid separation in units of meters */ + uint8_t sats_in_use; /*!< Number of satellites in use */ + uint8_t fix; /*!< Fix status. `0` = invalid, `1` = GPS fix, `2` = DGPS fix, `3` = PPS fix */ + uint8_t hours; /*!< Hours in UTC */ + uint8_t minutes; /*!< Minutes in UTC */ + uint8_t seconds; /*!< Seconds in UTC */ +#endif /* LWGPS_CFG_STATEMENT_GPGGA || __DOXYGEN__ */ #if LWGPS_CFG_STATEMENT_GPGSA || __DOXYGEN__ /* Information related to GPGSA statement */ - lwgps_float_t dop_h; /*!< Dolution of precision, horizontal */ - lwgps_float_t dop_v; /*!< Dolution of precision, vertical */ - lwgps_float_t dop_p; /*!< Dolution of precision, position */ - uint8_t fix_mode; /*!< Fix mode. `1` = NO fix, `2` = 2D fix, `3` = 3D fix */ - uint8_t satellites_ids[12]; /*!< List of satellite IDs in use. Valid range is `0` to `sats_in_use` */ -#endif /* LWGPS_CFG_STATEMENT_GPGSA || __DOXYGEN__ */ + lwgps_float_t dop_h; /*!< Dolution of precision, horizontal */ + lwgps_float_t dop_v; /*!< Dolution of precision, vertical */ + lwgps_float_t dop_p; /*!< Dolution of precision, position */ + uint8_t fix_mode; /*!< Fix mode. `1` = NO fix, `2` = 2D fix, `3` = 3D fix */ + uint8_t satellites_ids[12]; /*!< List of satellite IDs in use. Valid range is `0` to `sats_in_use` */ +#endif /* LWGPS_CFG_STATEMENT_GPGSA || __DOXYGEN__ */ #if LWGPS_CFG_STATEMENT_GPGSV || __DOXYGEN__ /* Information related to GPGSV statement */ - uint8_t sats_in_view; /*!< Number of satellites in view */ + uint8_t sats_in_view; /*!< Number of satellites in view */ #if LWGPS_CFG_STATEMENT_GPGSV_SAT_DET || __DOXYGEN__ lwgps_sat_t sats_in_view_desc[12]; #endif /* LWGPS_CFG_STATEMENT_GPGSV_SAT_DET || __DOXYGEN__ */ @@ -119,14 +119,14 @@ typedef struct { #if LWGPS_CFG_STATEMENT_GPRMC || __DOXYGEN__ /* Information related to GPRMC statement */ - uint8_t is_valid; /*!< GPS valid status */ - lwgps_float_t speed; /*!< Ground speed in knots */ - lwgps_float_t course; /*!< Ground coarse */ - lwgps_float_t variation; /*!< Magnetic variation */ - uint8_t date; /*!< Fix date */ - uint8_t month; /*!< Fix month */ - uint8_t year; /*!< Fix year */ -#endif /* LWGPS_CFG_STATEMENT_GPRMC || __DOXYGEN__ */ + uint8_t is_valid; /*!< GPS valid status */ + lwgps_float_t speed; /*!< Ground speed in knots */ + lwgps_float_t course; /*!< Ground coarse */ + lwgps_float_t variation; /*!< Magnetic variation */ + uint8_t date; /*!< Fix date */ + uint8_t month; /*!< Fix month */ + uint8_t year; /*!< Fix year */ +#endif /* LWGPS_CFG_STATEMENT_GPRMC || __DOXYGEN__ */ #if LWGPS_CFG_STATEMENT_PUBX_TIME || __DOXYGEN__ #if !LWGPS_CFG_STATEMENT_GPGGA && !__DOXYGEN__ @@ -142,87 +142,87 @@ typedef struct { uint8_t year; #endif /* !LWGPS_CFG_STATEMENT_GPRMC && !__DOXYGEN__ */ /* fields only available in PUBX_TIME */ - lwgps_float_t utc_tow; /*!< UTC TimeOfWeek, eg 113851.00 */ - uint16_t utc_wk; /*!< UTC week number, continues beyond 1023 */ - uint8_t leap_sec; /*!< UTC leap seconds; UTC + leap_sec = TAI */ - uint32_t clk_bias; /*!< Receiver clock bias, eg 1930035 */ - lwgps_float_t clk_drift; /*!< Receiver clock drift, eg -2660.664 */ - uint32_t tp_gran; /*!< Time pulse granularity, eg 43 */ -#endif /* LWGPS_CFG_STATEMENT_PUBX_TIME || __DOXYGEN__ */ + lwgps_float_t utc_tow; /*!< UTC TimeOfWeek, eg 113851.00 */ + uint16_t utc_wk; /*!< UTC week number, continues beyond 1023 */ + uint8_t leap_sec; /*!< UTC leap seconds; UTC + leap_sec = TAI */ + uint32_t clk_bias; /*!< Receiver clock bias, eg 1930035 */ + lwgps_float_t clk_drift; /*!< Receiver clock drift, eg -2660.664 */ + uint32_t tp_gran; /*!< Time pulse granularity, eg 43 */ +#endif /* LWGPS_CFG_STATEMENT_PUBX_TIME || __DOXYGEN__ */ #if !__DOXYGEN__ struct { - lwgps_statement_t stat; /*!< Statement index */ - char term_str[13]; /*!< Current term in string format */ - uint8_t term_pos; /*!< Current index position in term */ - uint8_t term_num; /*!< Current term number */ + lwgps_statement_t stat; /*!< Statement index */ + char term_str[13]; /*!< Current term in string format */ + uint8_t term_pos; /*!< Current index position in term */ + uint8_t term_num; /*!< Current term number */ - uint8_t star; /*!< Star detected flag */ + uint8_t star; /*!< Star detected flag */ #if LWGPS_CFG_CRC - uint8_t crc_calc; /*!< Calculated CRC string */ -#endif /* LWGPS_CFG_CRC */ + uint8_t crc_calc; /*!< Calculated CRC string */ +#endif /* LWGPS_CFG_CRC */ union { - uint8_t dummy; /*!< Dummy byte */ + uint8_t dummy; /*!< Dummy byte */ #if LWGPS_CFG_STATEMENT_GPGGA struct { - lwgps_float_t latitude; /*!< GPS latitude position in degrees */ - lwgps_float_t longitude; /*!< GPS longitude position in degrees */ - lwgps_float_t altitude; /*!< GPS altitude in meters */ - lwgps_float_t geo_sep; /*!< Geoid separation in units of meters */ - uint8_t sats_in_use; /*!< Number of satellites currently in use */ - uint8_t fix; /*!< Type of current fix, `0` = Invalid, `1` = GPS fix, `2` = Differential GPS fix */ - uint8_t hours; /*!< Current UTC hours */ - uint8_t minutes; /*!< Current UTC minutes */ - uint8_t seconds; /*!< Current UTC seconds */ - } gga; /*!< GPGGA message */ -#endif /* LWGPS_CFG_STATEMENT_GPGGA */ + lwgps_float_t latitude; /*!< GPS latitude position in degrees */ + lwgps_float_t longitude; /*!< GPS longitude position in degrees */ + lwgps_float_t altitude; /*!< GPS altitude in meters */ + lwgps_float_t geo_sep; /*!< Geoid separation in units of meters */ + uint8_t sats_in_use; /*!< Number of satellites currently in use */ + uint8_t fix; /*!< Type of current fix, `0` = Invalid, `1` = GPS fix, `2` = Differential GPS fix */ + uint8_t hours; /*!< Current UTC hours */ + uint8_t minutes; /*!< Current UTC minutes */ + uint8_t seconds; /*!< Current UTC seconds */ + } gga; /*!< GPGGA message */ +#endif /* LWGPS_CFG_STATEMENT_GPGGA */ #if LWGPS_CFG_STATEMENT_GPGSA struct { - lwgps_float_t dop_h; /*!< Horizontal dilution of precision */ - lwgps_float_t dop_v; /*!< Vertical dilution of precision */ - lwgps_float_t dop_p; /*!< Position dilution of precision */ - uint8_t fix_mode; /*!< Fix mode, `1` = No fix, `2` = 2D fix, `3` = 3D fix */ - uint8_t satellites_ids[12]; /*!< IDs of satellites currently in use */ - } gsa; /*!< GPGSA message */ -#endif /* LWGPS_CFG_STATEMENT_GPGSA */ + lwgps_float_t dop_h; /*!< Horizontal dilution of precision */ + lwgps_float_t dop_v; /*!< Vertical dilution of precision */ + lwgps_float_t dop_p; /*!< Position dilution of precision */ + uint8_t fix_mode; /*!< Fix mode, `1` = No fix, `2` = 2D fix, `3` = 3D fix */ + uint8_t satellites_ids[12]; /*!< IDs of satellites currently in use */ + } gsa; /*!< GPGSA message */ +#endif /* LWGPS_CFG_STATEMENT_GPGSA */ #if LWGPS_CFG_STATEMENT_GPGSV struct { - uint8_t sats_in_view; /*!< Number of stallites in view */ - uint8_t stat_num; /*!< Satellite line number during parsing GPGSV data */ - } gsv; /*!< GPGSV message */ -#endif /* LWGPS_CFG_STATEMENT_GPGSV */ + uint8_t sats_in_view; /*!< Number of stallites in view */ + uint8_t stat_num; /*!< Satellite line number during parsing GPGSV data */ + } gsv; /*!< GPGSV message */ +#endif /* LWGPS_CFG_STATEMENT_GPGSV */ #if LWGPS_CFG_STATEMENT_GPRMC struct { - uint8_t is_valid; /*!< Status whether GPS status is valid or not */ - uint8_t date; /*!< Current UTC date */ - uint8_t month; /*!< Current UTC month */ - uint8_t year; /*!< Current UTC year */ - lwgps_float_t speed; /*!< Current spead over the ground in knots */ - lwgps_float_t course; /*!< Current course over ground */ - lwgps_float_t variation; /*!< Current magnetic variation in degrees */ - } rmc; /*!< GPRMC message */ -#endif /* LWGPS_CFG_STATEMENT_GPRMC */ + uint8_t is_valid; /*!< Status whether GPS status is valid or not */ + uint8_t date; /*!< Current UTC date */ + uint8_t month; /*!< Current UTC month */ + uint8_t year; /*!< Current UTC year */ + lwgps_float_t speed; /*!< Current spead over the ground in knots */ + lwgps_float_t course; /*!< Current course over ground */ + lwgps_float_t variation; /*!< Current magnetic variation in degrees */ + } rmc; /*!< GPRMC message */ +#endif /* LWGPS_CFG_STATEMENT_GPRMC */ #if LWGPS_CFG_STATEMENT_PUBX_TIME struct { - uint8_t hours; /*!< Current UTC hours */ - uint8_t minutes; /*!< Current UTC minutes */ - uint8_t seconds; /*!< Current UTC seconds */ - uint8_t date; /*!< Current UTC date */ - uint8_t month; /*!< Current UTC month */ - uint8_t year; /*!< Current UTC year */ - lwgps_float_t utc_tow; /*!< UTC TimeOfWeek, eg 113851.00 */ - uint16_t utc_wk; /*!< UTC week number, continues beyond 1023 */ - uint8_t leap_sec; /*!< UTC leap seconds; UTC + leap_sec = TAI */ - uint32_t clk_bias; /*!< Receiver clock bias, eg 1930035 */ - lwgps_float_t clk_drift; /*!< Receiver clock drift, eg -2660.664 */ - uint32_t tp_gran; /*!< Time pulse granularity, eg 43 */ - } time; /*!< PUBX TIME message */ -#endif /* LWGPS_CFG_STATEMENT_PUBX_TIME */ - } data; /*!< Union with data for each information */ - } p; /*!< Structure with private data */ -#endif /* !__DOXYGEN__ */ + uint8_t hours; /*!< Current UTC hours */ + uint8_t minutes; /*!< Current UTC minutes */ + uint8_t seconds; /*!< Current UTC seconds */ + uint8_t date; /*!< Current UTC date */ + uint8_t month; /*!< Current UTC month */ + uint8_t year; /*!< Current UTC year */ + lwgps_float_t utc_tow; /*!< UTC TimeOfWeek, eg 113851.00 */ + uint16_t utc_wk; /*!< UTC week number, continues beyond 1023 */ + uint8_t leap_sec; /*!< UTC leap seconds; UTC + leap_sec = TAI */ + uint32_t clk_bias; /*!< Receiver clock bias, eg 1930035 */ + lwgps_float_t clk_drift; /*!< Receiver clock drift, eg -2660.664 */ + uint32_t tp_gran; /*!< Time pulse granularity, eg 43 */ + } time; /*!< PUBX TIME message */ +#endif /* LWGPS_CFG_STATEMENT_PUBX_TIME */ + } data; /*!< Union with data for each information */ + } p; /*!< Structure with private data */ +#endif /* !__DOXYGEN__ */ } lwgps_t; /** @@ -230,27 +230,27 @@ typedef struct { */ typedef enum { /* Metric values */ - lwgps_speed_kps, /*!< Kilometers per second */ - lwgps_speed_kph, /*!< Kilometers per hour */ - lwgps_speed_mps, /*!< Meters per second */ - lwgps_speed_mpm, /*!< Meters per minute */ + lwgps_speed_kps, /*!< Kilometers per second */ + lwgps_speed_kph, /*!< Kilometers per hour */ + lwgps_speed_mps, /*!< Meters per second */ + lwgps_speed_mpm, /*!< Meters per minute */ /* Imperial values */ - lwgps_speed_mips, /*!< Miles per second */ - lwgps_speed_mph, /*!< Miles per hour */ - lwgps_speed_fps, /*!< Foots per second */ - lwgps_speed_fpm, /*!< Foots per minute */ + lwgps_speed_mips, /*!< Miles per second */ + lwgps_speed_mph, /*!< Miles per hour */ + lwgps_speed_fps, /*!< Foots per second */ + lwgps_speed_fpm, /*!< Foots per minute */ /* Optimized for runners/joggers */ - lwgps_speed_mpk, /*!< Minutes per kilometer */ - lwgps_speed_spk, /*!< Seconds per kilometer */ - lwgps_speed_sp100m, /*!< Seconds per 100 meters */ - lwgps_speed_mipm, /*!< Minutes per mile */ - lwgps_speed_spm, /*!< Seconds per mile */ - lwgps_speed_sp100y, /*!< Seconds per 100 yards */ + lwgps_speed_mpk, /*!< Minutes per kilometer */ + lwgps_speed_spk, /*!< Seconds per kilometer */ + lwgps_speed_sp100m, /*!< Seconds per 100 meters */ + lwgps_speed_mipm, /*!< Minutes per mile */ + lwgps_speed_spm, /*!< Seconds per mile */ + lwgps_speed_sp100y, /*!< Seconds per 100 yards */ /* Nautical values */ - lwgps_speed_smph, /*!< Sea miles per hour */ + lwgps_speed_smph, /*!< Sea miles per hour */ } lwgps_speed_t; /** @@ -266,19 +266,20 @@ typedef void (*lwgps_process_fn)(lwgps_statement_t res); * \return `1` on success, `0` otherwise */ #if LWGPS_CFG_STATEMENT_GPRMC || __DOXYGEN__ -#define lwgps_is_valid(_gh) ((_gh)->is_valid) +#define lwgps_is_valid(_gh) ((_gh)->is_valid) #else -#define lwgps_is_valid(_gh) (0) +#define lwgps_is_valid(_gh) (0) #endif /* LWGPS_CFG_STATEMENT_GPRMC || __DOXYGEN__ */ -uint8_t lwgps_init(lwgps_t* gh); +uint8_t lwgps_init(lwgps_t* gh); #if LWGPS_CFG_STATUS || __DOXYGEN__ -uint8_t lwgps_process(lwgps_t* gh, const void* data, size_t len, lwgps_process_fn evt_fn); -#else /* LWGPS_CFG_STATUS */ -uint8_t lwgps_process(lwgps_t* gh, const void* data, size_t len); +uint8_t lwgps_process(lwgps_t* gh, const void* data, size_t len, lwgps_process_fn evt_fn); +#else /* LWGPS_CFG_STATUS */ +uint8_t lwgps_process(lwgps_t* gh, const void* data, size_t len); #endif /* !LWGPS_CFG_STATUS */ -uint8_t lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, lwgps_float_t loe, lwgps_float_t* d, lwgps_float_t* b); -lwgps_float_t lwgps_to_speed(lwgps_float_t sik, lwgps_speed_t ts); +uint8_t lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, lwgps_float_t loe, + lwgps_float_t* d, lwgps_float_t* b); +lwgps_float_t lwgps_to_speed(lwgps_float_t sik, lwgps_speed_t ts); /** * \} diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index 8c07945..ae25350 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -59,7 +59,7 @@ extern "C" { * `double` is used as variable type when enabled, `float` when disabled. */ #ifndef LWGPS_CFG_DOUBLE -#define LWGPS_CFG_DOUBLE 1 +#define LWGPS_CFG_DOUBLE 1 #endif /** @@ -69,7 +69,7 @@ extern "C" { * \note This is an extension, so not enabled by default. */ #ifndef LWGPS_CFG_STATUS -#define LWGPS_CFG_STATUS 0 +#define LWGPS_CFG_STATUS 0 #endif /** @@ -80,7 +80,7 @@ extern "C" { * - Number of satellites in use, fix (no fix, GPS, DGPS), UTC time */ #ifndef LWGPS_CFG_STATEMENT_GPGGA -#define LWGPS_CFG_STATEMENT_GPGGA 1 +#define LWGPS_CFG_STATEMENT_GPGGA 1 #endif /** @@ -92,7 +92,7 @@ extern "C" { * - IDs of satellites in use */ #ifndef LWGPS_CFG_STATEMENT_GPGSA -#define LWGPS_CFG_STATEMENT_GPGSA 1 +#define LWGPS_CFG_STATEMENT_GPGSA 1 #endif /** @@ -105,7 +105,7 @@ extern "C" { * - UTC date */ #ifndef LWGPS_CFG_STATEMENT_GPRMC -#define LWGPS_CFG_STATEMENT_GPRMC 1 +#define LWGPS_CFG_STATEMENT_GPRMC 1 #endif /** @@ -116,7 +116,7 @@ extern "C" { * - Optional details of each satellite in view. See \ref LWGPS_CFG_STATEMENT_GPGSV_SAT_DET */ #ifndef LWGPS_CFG_STATEMENT_GPGSV -#define LWGPS_CFG_STATEMENT_GPGSV 1 +#define LWGPS_CFG_STATEMENT_GPGSV 1 #endif /** @@ -126,7 +126,7 @@ extern "C" { * \note When this feature is disabled, only number of "satellites in view" is parsed */ #ifndef LWGPS_CFG_STATEMENT_GPGSV_SAT_DET -#define LWGPS_CFG_STATEMENT_GPGSV_SAT_DET 0 +#define LWGPS_CFG_STATEMENT_GPGSV_SAT_DET 0 #endif /** @@ -137,7 +137,7 @@ extern "C" { * so disabled by default. */ #ifndef LWGPS_CFG_STATEMENT_PUBX -#define LWGPS_CFG_STATEMENT_PUBX 0 +#define LWGPS_CFG_STATEMENT_PUBX 0 #endif /** @@ -155,7 +155,7 @@ extern "C" { * This configure option requires LWGPS_CFG_STATEMENT_PUBX */ #ifndef LWGPS_CFG_STATEMENT_PUBX_TIME -#define LWGPS_CFG_STATEMENT_PUBX_TIME 0 +#define LWGPS_CFG_STATEMENT_PUBX_TIME 0 #endif /** @@ -164,7 +164,7 @@ extern "C" { * \note When not enabled, CRC check is ignored */ #ifndef LWGPS_CFG_CRC -#define LWGPS_CFG_CRC 1 +#define LWGPS_CFG_CRC 1 #endif /* Guard against accidental parser breakage */ diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index 12bfda1..64043b0 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -32,32 +32,40 @@ * Version: v2.1.0 */ #include -#include #include +#include #include "lwgps/lwgps.h" -#define FLT(x) ((lwgps_float_t)(x)) -#define D2R(x) FLT(FLT(x) * FLT(0.01745329251994)) /*!< Degrees to radians */ -#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 FLT(x) ((lwgps_float_t)(x)) +#define D2R(x) FLT(FLT(x) * FLT(0.01745329251994)) /*!< Degrees to radians */ +#define R2D(x) FLT(FLT(x) * FLT(57.29577951308232)) /*!< Radians to degrees */ +#define EARTH_RADIUS FLT(6371.0) /*!< Earth radius in units of kilometers */ #if LWGPS_CFG_CRC -#define CRC_ADD(_gh, ch) (_gh)->p.crc_calc ^= (uint8_t)(ch) +#define CRC_ADD(_gh, ch) (_gh)->p.crc_calc ^= (uint8_t)(ch) #else #define CRC_ADD(_gh, ch) #endif /* LWGPS_CFG_CRC */ -#define TERM_ADD(_gh, ch) do { \ - if ((_gh)->p.term_pos < (sizeof((_gh)->p.term_str) - 1)) { \ - (_gh)->p.term_str[(_gh)->p.term_pos] = (ch);\ - (_gh)->p.term_str[++(_gh)->p.term_pos] = 0; \ - } \ +#define TERM_ADD(_gh, ch) \ + do { \ + if ((_gh)->p.term_pos < (sizeof((_gh)->p.term_str) - 1)) { \ + (_gh)->p.term_str[(_gh)->p.term_pos] = (ch); \ + (_gh)->p.term_str[++(_gh)->p.term_pos] = 0; \ + } \ + } while (0) +#define TERM_NEXT(_gh) \ + do { \ + (_gh)->p.term_str[((_gh)->p.term_pos = 0)] = 0; \ + ++(_gh)->p.term_num; \ } while (0) -#define TERM_NEXT(_gh) do { (_gh)->p.term_str[((_gh)->p.term_pos = 0)] = 0; ++(_gh)->p.term_num; } while (0) -#define CIN(x) ((x) >= '0' && (x) <= '9') -#define CIHN(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F')) -#define CTN(x) ((x) - '0') -#define CHTN(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : (((x) >= 'a' && (x) <= 'z') ? ((x) - 'a' + 10) : (((x) >= 'A' && (x) <= 'Z') ? ((x) - 'A' + 10) : 0))) +#define CIN(x) ((x) >= '0' && (x) <= '9') +#define CIHN(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F')) +#define CTN(x) ((x) - '0') +#define CHTN(x) \ + (((x) >= '0' && (x) <= '9') \ + ? ((x) - '0') \ + : (((x) >= 'a' && (x) <= 'z') ? ((x) - 'a' + 10) : (((x) >= 'A' && (x) <= 'Z') ? ((x) - 'A' + 10) : 0))) /** * \brief Parse number as integer @@ -73,7 +81,7 @@ prv_parse_number(lwgps_t* gh, const char* t) { if (t == NULL) { t = gh->p.term_str; } - for (; t != NULL && *t == ' '; ++t) {} /* Strip leading spaces */ + for (; t != NULL && *t == ' '; ++t) {} /* Strip leading spaces */ minus = (*t == '-' ? (++t, 1) : 0); for (; t != NULL && CIN(*t); ++t) { @@ -95,15 +103,15 @@ prv_parse_float_number(lwgps_t* gh, const char* t) { if (t == NULL) { t = gh->p.term_str; } - for (; t != NULL && *t == ' '; ++t) {} /* Strip leading spaces */ + for (; t != NULL && *t == ' '; ++t) {} /* Strip leading spaces */ #if LWGPS_CFG_DOUBLE - res = strtod(t, NULL); /* Parse string to double */ -#else /* LWGPS_CFG_DOUBLE */ - res = strtof(t, NULL); /* Parse string to float */ -#endif /* !LWGPS_CFG_DOUBLE */ + res = strtod(t, NULL); /* Parse string to double */ +#else /* LWGPS_CFG_DOUBLE */ + res = strtof(t, NULL); /* Parse string to float */ +#endif /* !LWGPS_CFG_DOUBLE */ - return FLT(res); /* Return casted value, based on float size */ + return FLT(res); /* Return casted value, based on float size */ } /** @@ -117,10 +125,10 @@ static lwgps_float_t prv_parse_lat_long(lwgps_t* gh) { lwgps_float_t ll, deg, min; - ll = prv_parse_float_number(gh, NULL); /* Parse value as double */ - deg = FLT((int)((int)ll / 100)); /* Get absolute degrees value, interested in integer part only */ - min = ll - (deg * FLT(100)); /* Get remaining part from full number, minutes */ - ll = deg + (min / FLT(60.0)); /* Calculate latitude/longitude */ + ll = prv_parse_float_number(gh, NULL); /* Parse value as double */ + deg = FLT((int)((int)ll / 100)); /* Get absolute degrees value, interested in integer part only */ + min = ll - (deg * FLT(100)); /* Get remaining part from full number, minutes */ + ll = deg + (min / FLT(60.0)); /* Calculate latitude/longitude */ return ll; } @@ -132,7 +140,7 @@ prv_parse_lat_long(lwgps_t* gh) { */ static uint8_t prv_parse_term(lwgps_t* gh) { - if (gh->p.term_num == 0) { /* Check string type */ + if (gh->p.term_num == 0) { /* Check string type */ if (0) { #if LWGPS_CFG_STATEMENT_GPGGA } else if (!strncmp(gh->p.term_str, "$GPGGA", 6) || !strncmp(gh->p.term_str, "$GNGGA", 6)) { @@ -155,7 +163,7 @@ prv_parse_term(lwgps_t* gh) { gh->p.stat = STAT_UBX; #endif /* LWGPS_CFG_STATEMENT_PUBX */ } else { - gh->p.stat = STAT_UNKNOWN; /* Invalid statement for library */ + gh->p.stat = STAT_UNKNOWN; /* Invalid statement for library */ } return 1; } @@ -163,39 +171,39 @@ prv_parse_term(lwgps_t* gh) { /* Start parsing terms */ if (gh->p.stat == STAT_UNKNOWN) { #if LWGPS_CFG_STATEMENT_GPGGA - } else if (gh->p.stat == STAT_GGA) { /* Process GPGGA statement */ + } else if (gh->p.stat == STAT_GGA) { /* Process GPGGA statement */ switch (gh->p.term_num) { - case 1: /* Process UTC time */ + case 1: /* Process UTC time */ gh->p.data.gga.hours = 10 * CTN(gh->p.term_str[0]) + CTN(gh->p.term_str[1]); gh->p.data.gga.minutes = 10 * CTN(gh->p.term_str[2]) + CTN(gh->p.term_str[3]); gh->p.data.gga.seconds = 10 * CTN(gh->p.term_str[4]) + CTN(gh->p.term_str[5]); break; - case 2: /* Latitude */ - gh->p.data.gga.latitude = prv_parse_lat_long(gh); /* Parse latitude */ + case 2: /* Latitude */ + gh->p.data.gga.latitude = prv_parse_lat_long(gh); /* Parse latitude */ break; - case 3: /* Latitude north/south information */ + case 3: /* Latitude north/south information */ if (gh->p.term_str[0] == 'S' || gh->p.term_str[0] == 's') { gh->p.data.gga.latitude = -gh->p.data.gga.latitude; } break; - case 4: /* Longitude */ - gh->p.data.gga.longitude = prv_parse_lat_long(gh); /* Parse longitude */ + case 4: /* Longitude */ + gh->p.data.gga.longitude = prv_parse_lat_long(gh); /* Parse longitude */ break; - case 5: /* Longitude east/west information */ + case 5: /* Longitude east/west information */ if (gh->p.term_str[0] == 'W' || gh->p.term_str[0] == 'w') { gh->p.data.gga.longitude = -gh->p.data.gga.longitude; } break; - case 6: /* Fix status */ + case 6: /* Fix status */ gh->p.data.gga.fix = (uint8_t)prv_parse_number(gh, NULL); break; - case 7: /* Satellites in use */ + case 7: /* Satellites in use */ gh->p.data.gga.sats_in_use = (uint8_t)prv_parse_number(gh, NULL); break; - case 9: /* Altitude */ + case 9: /* Altitude */ gh->p.data.gga.altitude = prv_parse_float_number(gh, NULL); break; - case 11: /* Altitude above ellipsoid */ + case 11: /* Altitude above ellipsoid */ gh->p.data.gga.geo_sep = prv_parse_float_number(gh, NULL); break; default: @@ -203,18 +211,18 @@ prv_parse_term(lwgps_t* gh) { } #endif /* LWGPS_CFG_STATEMENT_GPGGA */ #if LWGPS_CFG_STATEMENT_GPGSA - } else if (gh->p.stat == STAT_GSA) { /* Process GPGSA statement */ + } else if (gh->p.stat == STAT_GSA) { /* Process GPGSA statement */ switch (gh->p.term_num) { - case 2: /* Process fix mode */ + case 2: /* Process fix mode */ gh->p.data.gsa.fix_mode = (uint8_t)prv_parse_number(gh, NULL); break; - case 15: /* Process PDOP */ + case 15: /* Process PDOP */ gh->p.data.gsa.dop_p = prv_parse_float_number(gh, NULL); break; - case 16: /* Process HDOP */ + case 16: /* Process HDOP */ gh->p.data.gsa.dop_h = prv_parse_float_number(gh, NULL); break; - case 17: /* Process VDOP */ + case 17: /* Process VDOP */ gh->p.data.gsa.dop_v = prv_parse_float_number(gh, NULL); break; default: @@ -226,23 +234,23 @@ prv_parse_term(lwgps_t* gh) { } #endif /* LWGPS_CFG_STATEMENT_GPGSA */ #if LWGPS_CFG_STATEMENT_GPGSV - } else if (gh->p.stat == STAT_GSV) { /* Process GPGSV statement */ + } else if (gh->p.stat == STAT_GSV) { /* Process GPGSV statement */ switch (gh->p.term_num) { - case 2: /* Current GPGSV statement number */ + case 2: /* Current GPGSV statement number */ gh->p.data.gsv.stat_num = (uint8_t)prv_parse_number(gh, NULL); break; - case 3: /* Process satellites in view */ + case 3: /* Process satellites in view */ gh->p.data.gsv.sats_in_view = (uint8_t)prv_parse_number(gh, NULL); break; default: #if LWGPS_CFG_STATEMENT_GPGSV_SAT_DET - if (gh->p.term_num >= 4 && gh->p.term_num <= 19) { /* Check current term number */ - uint8_t index, term_num = gh->p.term_num - 4; /* Normalize term number from 4-19 to 0-15 */ + if (gh->p.term_num >= 4 && gh->p.term_num <= 19) { /* Check current term number */ + uint8_t index, term_num = gh->p.term_num - 4; /* Normalize term number from 4-19 to 0-15 */ uint16_t value; - index = ((gh->p.data.gsv.stat_num - 1) << 0x02) + (term_num >> 2); /* Get array index */ + index = ((gh->p.data.gsv.stat_num - 1) << 0x02) + (term_num >> 2); /* Get array index */ if (index < sizeof(gh->sats_in_view_desc) / sizeof(gh->sats_in_view_desc[0])) { - value = (uint16_t)prv_parse_number(gh, NULL); /* Parse number as integer */ + value = (uint16_t)prv_parse_number(gh, NULL); /* Parse number as integer */ switch (term_num & 0x03) { case 0: gh->sats_in_view_desc[index].num = value; @@ -266,26 +274,26 @@ prv_parse_term(lwgps_t* gh) { } #endif /* LWGPS_CFG_STATEMENT_GPGSV */ #if LWGPS_CFG_STATEMENT_GPRMC - } else if (gh->p.stat == STAT_RMC) { /* Process GPRMC statement */ + } else if (gh->p.stat == STAT_RMC) { /* Process GPRMC statement */ switch (gh->p.term_num) { - case 2: /* Process valid status */ + case 2: /* Process valid status */ gh->p.data.rmc.is_valid = (gh->p.term_str[0] == 'A'); break; - case 7: /* Process ground speed in knots */ + case 7: /* Process ground speed in knots */ gh->p.data.rmc.speed = prv_parse_float_number(gh, NULL); break; - case 8: /* Process true ground coarse */ + case 8: /* Process true ground coarse */ gh->p.data.rmc.course = prv_parse_float_number(gh, NULL); break; - case 9: /* Process date */ + case 9: /* Process date */ gh->p.data.rmc.date = (uint8_t)(10 * CTN(gh->p.term_str[0]) + CTN(gh->p.term_str[1])); gh->p.data.rmc.month = (uint8_t)(10 * CTN(gh->p.term_str[2]) + CTN(gh->p.term_str[3])); gh->p.data.rmc.year = (uint8_t)(10 * CTN(gh->p.term_str[4]) + CTN(gh->p.term_str[5])); break; - case 10: /* Process magnetic variation */ + case 10: /* Process magnetic variation */ gh->p.data.rmc.variation = prv_parse_float_number(gh, NULL); break; - case 11: /* Process magnetic variation east/west */ + case 11: /* Process magnetic variation east/west */ if (gh->p.term_str[0] == 'W' || gh->p.term_str[0] == 'w') { gh->p.data.rmc.variation = -gh->p.data.rmc.variation; } @@ -295,50 +303,48 @@ prv_parse_term(lwgps_t* gh) { } #endif /* LWGPS_CFG_STATEMENT_GPRMC */ #if LWGPS_CFG_STATEMENT_PUBX - } else if (gh->p.stat == STAT_UBX) { /* Disambiguate generic PUBX statement */ + } 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 LWGPS_CFG_STATEMENT_PUBX_TIME - } else if (gh->p.stat == STAT_UBX_TIME) { /* Process PUBX (uBlox) TIME statement */ + } 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 */ + 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 */ + 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 */ + case 4: /* Process UTC TimeOfWeek */ gh->p.data.time.utc_tow = prv_parse_float_number(gh, NULL); break; - case 5: /* Process UTC WeekNumber */ + case 5: /* Process UTC WeekNumber */ gh->p.data.time.utc_wk = prv_parse_number(gh, NULL); break; - case 6: /* Process UTC leap seconds */ + 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]); + 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]); + 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 */ + case 7: /* Process clock bias */ gh->p.data.time.clk_bias = prv_parse_number(gh, NULL); break; - case 8: /* Process clock drift */ + case 8: /* Process clock drift */ gh->p.data.time.clk_drift = prv_parse_float_number(gh, NULL); break; - case 9: /* Process time pulse granularity */ + case 9: /* Process time pulse granularity */ gh->p.data.time.tp_gran = prv_parse_number(gh, NULL); break; default: @@ -359,11 +365,12 @@ prv_parse_term(lwgps_t* gh) { static uint8_t prv_check_crc(lwgps_t* gh) { uint8_t crc; - crc = (uint8_t)((CHTN(gh->p.term_str[0]) & 0x0F) << 0x04) | (CHTN(gh->p.term_str[1]) & 0x0F); /* Convert received CRC from string (hex) to number */ - return gh->p.crc_calc == crc; /* They must match! */ + crc = (uint8_t)((CHTN(gh->p.term_str[0]) & 0x0F) << 0x04) + | (CHTN(gh->p.term_str[1]) & 0x0F); /* Convert received CRC from string (hex) to number */ + return gh->p.crc_calc == crc; /* They must match! */ } #else -#define prv_check_crc(_gh) (1) +#define prv_check_crc(_gh) (1) #endif /* LWGPS_CFG_CRC */ /** @@ -434,7 +441,7 @@ prv_copy_from_tmp_memory(lwgps_t* gh) { */ uint8_t lwgps_init(lwgps_t* gh) { - memset(gh, 0x00, sizeof(*gh)); /* Reset structure */ + memset(gh, 0x00, sizeof(*gh)); /* Reset structure */ return 1; } @@ -450,27 +457,27 @@ lwgps_init(lwgps_t* gh) { uint8_t #if LWGPS_CFG_STATUS || __DOXYGEN__ lwgps_process(lwgps_t* gh, const void* data, size_t len, lwgps_process_fn evt_fn) { -#else /* LWGPS_CFG_STATUS */ +#else /* LWGPS_CFG_STATUS */ lwgps_process(lwgps_t* gh, const void* data, size_t len) { #endif /* !LWGPS_CFG_STATUS */ const uint8_t* d = data; - 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 */ - } else if (*d == ',') { /* Term separator character */ - prv_parse_term(gh); /* Parse term we have currently in memory */ - CRC_ADD(gh, *d); /* Add character to CRC computation */ - TERM_NEXT(gh); /* Start with next term */ - } else if (*d == '*') { /* Start indicates end of data for CRC computation */ - prv_parse_term(gh); /* Parse term we have currently in memory */ - gh->p.star = 1; /* STAR detected */ - TERM_NEXT(gh); /* Start with next term */ + 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 */ + } else if (*d == ',') { /* Term separator character */ + prv_parse_term(gh); /* Parse term we have currently in memory */ + CRC_ADD(gh, *d); /* Add character to CRC computation */ + TERM_NEXT(gh); /* Start with next term */ + } else if (*d == '*') { /* Start indicates end of data for CRC computation */ + prv_parse_term(gh); /* Parse term we have currently in memory */ + gh->p.star = 1; /* STAR detected */ + TERM_NEXT(gh); /* Start with next term */ } else if (*d == '\r') { - if (prv_check_crc(gh)) { /* Check for CRC result */ + if (prv_check_crc(gh)) { /* Check for CRC result */ /* CRC is OK, in theory we can copy data from statements to user data */ - prv_copy_from_tmp_memory(gh); /* Copy memory from temporary to user memory */ + prv_copy_from_tmp_memory(gh); /* Copy memory from temporary to user memory */ #if LWGPS_CFG_STATUS if (evt_fn != NULL) { evt_fn(gh->p.stat); @@ -480,10 +487,10 @@ lwgps_process(lwgps_t* gh, const void* data, size_t len) { #endif /* LWGPS_CFG_STATUS */ } } else { - if (!gh->p.star) { /* Add to CRC only if star not yet detected */ - CRC_ADD(gh, *d); /* Add to CRC */ + 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 */ + TERM_ADD(gh, *d); /* Add character to term */ } } return 1; @@ -500,7 +507,8 @@ lwgps_process(lwgps_t* gh, const void* data, size_t len) { * \return `1` on success, `0` otherwise */ uint8_t -lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, lwgps_float_t loe, lwgps_float_t* d, lwgps_float_t* b) { +lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, lwgps_float_t loe, lwgps_float_t* d, + lwgps_float_t* b) { lwgps_float_t df, dfi, a; if (d == NULL && b == NULL) { @@ -528,7 +536,7 @@ lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, #if LWGPS_CFG_DOUBLE a = FLT(sin(df * 0.5) * sin(df * 0.5) + sin(dfi * 0.5) * sin(dfi * 0.5) * cos(las) * cos(lae)); *d = FLT(EARTH_RADIUS * 2.0 * atan2(sqrt(a), sqrt(1.0 - a)) * 1000.0); -#else /* LWGPS_CFG_DOUBLE */ +#else /* LWGPS_CFG_DOUBLE */ a = FLT(sinf(df * 0.5f) * sinf(df * 0.5f) + sinf(dfi * 0.5f) * sinf(dfi * 0.5f) * cosf(las) * cosf(lae)); *d = FLT(EARTH_RADIUS * 2.0f * atan2f(sqrtf(a), sqrtf(1.0f - a)) * 1000.0f); #endif /* !LWGPS_CFG_DOUBLE */ @@ -552,15 +560,15 @@ lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, df = FLT(sin(loe - los) * cos(lae)); dfi = FLT(cos(las) * sin(lae) - sin(las) * cos(lae) * cos(loe - los)); - *b = R2D(atan2(df, dfi)); /* Calculate bearing and convert to degrees */ -#else /* LWGPS_CFG_DOUBLE */ + *b = R2D(atan2(df, dfi)); /* Calculate bearing and convert to degrees */ +#else /* LWGPS_CFG_DOUBLE */ df = FLT(sinf(loe - los) * cosf(lae)); dfi = FLT(cosf(las) * sinf(lae) - sinf(las) * cosf(lae) * cosf(loe - los)); - *b = R2D(atan2f(df, dfi)); /* Calculate bearing and convert to degrees */ -#endif /* !LWGPS_CFG_DOUBLE */ - if (*b < 0) { /* Check for negative angle */ - *b += FLT(360); /* Make bearing always positive */ + *b = R2D(atan2f(df, dfi)); /* Calculate bearing and convert to degrees */ +#endif /* !LWGPS_CFG_DOUBLE */ + if (*b < 0) { /* Check for negative angle */ + *b += FLT(360); /* Make bearing always positive */ } } return 1; From aa7db31885c40c828902fcf7a623199b145a43bc Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Thu, 1 Sep 2022 23:08:50 +0200 Subject: [PATCH 55/80] Fix wrong clang formatting --- .clang-format | 84 +++++++++++++++++++++++------------------------ CMakePresets.json | 10 ++++++ 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/.clang-format b/.clang-format index 490ba55..1fad350 100644 --- a/.clang-format +++ b/.clang-format @@ -1,5 +1,5 @@ --- -Language: Cpp +Language: Cpp # BasedOnStyle: LLVM AccessModifierOffset: -2 AlignAfterOpenBracket: Align @@ -16,7 +16,8 @@ AlignConsecutiveBitFields: AlignConsecutiveDeclarations: None AlignEscapedNewlines: Right AlignOperands: Align -InsertBraces: true # Control statements must have curly brackets +SortIncludes: false +InsertBraces: true # Control statements must have curly brackets AlignTrailingComments: true AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true @@ -36,21 +37,21 @@ AttributeMacros: BinPackArguments: true BinPackParameters: true BraceWrapping: - AfterCaseLabel: false - AfterClass: false + AfterCaseLabel: false + AfterClass: false AfterControlStatement: Never - AfterEnum: false - AfterFunction: false - AfterNamespace: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false + AfterStruct: false + AfterUnion: false AfterExternBlock: false - BeforeCatch: false - BeforeElse: false + BeforeCatch: false + BeforeElse: false BeforeLambdaBody: false - BeforeWhile: false - IndentBraces: false + BeforeWhile: false + IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true @@ -64,8 +65,8 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 120 -CommentPragmas: '^ IWYU pragma:' +ColumnLimit: 120 +CommentPragmas: "^ IWYU pragma:" QualifierAlignment: Leave CompactNamespaces: false ConstructorInitializerIndentWidth: 4 @@ -73,12 +74,12 @@ ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DeriveLineEnding: true DerivePointerAlignment: false -DisableFormat: false +DisableFormat: false EmptyLineAfterAccessModifier: Never EmptyLineBeforeAccessModifier: LogicalBlock ExperimentalAutoDetectBinPacking: false PackConstructorInitializers: BinPack -BasedOnStyle: '' +BasedOnStyle: "" ConstructorInitializerAllOnOneLineOrOnePerLine: false AllowAllConstructorInitializersOnNextLine: true FixNamespaceComments: true @@ -88,32 +89,32 @@ ForEachMacros: - BOOST_FOREACH IfMacros: - KJ_IF_MAYBE -IncludeBlocks: Preserve +IncludeBlocks: Preserve IncludeCategories: - - Regex: '^<(.*)>' - Priority: 0 - - Regex: '^"(.*)"' - Priority: 1 - - Regex: '(.*)' - Priority: 2 -IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' + - Regex: "^<(.*)>" + Priority: 0 + - Regex: '^"(.*)"' + Priority: 1 + - Regex: "(.*)" + Priority: 2 +IncludeIsMainRegex: "(Test)?$" +IncludeIsMainSourceRegex: "" IndentAccessModifiers: false IndentCaseLabels: true IndentCaseBlocks: false IndentGotoLabels: true IndentPPDirectives: None IndentExternBlock: AfterExternBlock -IndentRequires: true -IndentWidth: 4 +IndentRequires: true +IndentWidth: 4 IndentWrappedFunctionNames: false InsertTrailingCommas: None JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: true LambdaBodyIndentation: Signature -MacroBlockBegin: '' -MacroBlockEnd: '' +MacroBlockBegin: "" +MacroBlockEnd: "" MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCBinPackProtocolList: Auto @@ -132,13 +133,12 @@ PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PenaltyIndentedWhitespace: 0 PointerAlignment: Left -PPIndentWidth: -1 +PPIndentWidth: -1 ReferenceAlignment: Pointer -ReflowComments: false +ReflowComments: false RemoveBracesLLVM: false SeparateDefinitionBlocks: Always ShortNamespaceLines: 1 -SortIncludes: CaseSensitive SortJavaStaticImport: Before SortUsingDeclarations: true SpaceAfterCStyleCast: false @@ -152,7 +152,7 @@ SpaceBeforeParensOptions: AfterForeachMacros: true AfterFunctionDefinitionName: false AfterFunctionDeclarationName: false - AfterIfMacros: true + AfterIfMacros: true AfterOverloadedOperator: false BeforeNonEmptyParentheses: false SpaceAroundPointerQualifiers: Default @@ -160,26 +160,26 @@ SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyBlock: false SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never +SpacesInAngles: Never SpacesInConditionalStatement: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: -1 + Minimum: 1 + Maximum: -1 SpacesInParentheses: false SpacesInSquareBrackets: false SpaceBeforeSquareBrackets: false BitFieldColonSpacing: Both -Standard: Latest +Standard: Latest StatementAttributeLikeMacros: - Q_EMIT StatementMacros: - Q_UNUSED - QT_REQUIRE_VERSION -TabWidth: 8 -UseCRLF: false -UseTab: Never +TabWidth: 8 +UseCRLF: false +UseTab: Never WhitespaceSensitiveMacros: - STRINGIZE - PP_STRINGIZE @@ -189,5 +189,5 @@ WhitespaceSensitiveMacros: SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true -... +--- diff --git a/CMakePresets.json b/CMakePresets.json index 7d277c4..f99154c 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -26,5 +26,15 @@ "CMAKE_BUILD_TYPE": "Debug" } } + ], + "buildPresets": [ + { + "name": "Win32-Debug", + "configurePreset": "Win32-Debug" + }, + { + "name": "Win64-Debug", + "configurePreset": "Win64-Debug" + } ] } \ No newline at end of file From 87f6b2cb2d07e4565a7d817d619ba7978fdabd3e Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 30 Sep 2022 08:11:07 +0200 Subject: [PATCH 56/80] Update CMakeLists.txt --- CMakeLists.txt | 76 +++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ec0d15..f713b72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,45 +3,39 @@ cmake_minimum_required(VERSION 3.22) # Setup project project(LwLibPROJECT) -# ------------------------------------------------- -# This CMakeLists.txt is used only if it is a top-level file. -# Purpose of it is to be able to compile project in standalone way only -# -# When library sources are to be included in another project -# user shall use /lwgps/CMakeLists.txt instead -if (NOT PROJECT_IS_TOP_LEVEL) - message(FATAL_ERROR "This CMakeLists.txt can only be used as top-level. Use /lwgps/CMakeLists.txt for library include purpose") +if(NOT PROJECT_IS_TOP_LEVEL) + add_subdirectory(lwgps) +else() + # Set as executable + add_executable(${PROJECT_NAME}) + + # Add key executable block + target_sources(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/dev/main.c + ${CMAKE_CURRENT_LIST_DIR}/examples/test_code.c + ) + + # Add key include paths + target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/dev + ) + + # Compilation definition information + target_compile_definitions(${PROJECT_NAME} PUBLIC + WIN32 + _DEBUG + CONSOLE + LWGPS_DEV + ) + + # Compiler options + target_compile_options(${PROJECT_NAME} PRIVATE + -Wall + -Wextra + -Wpedantic + ) + + # Add subdir with lwgps and link to project + add_subdirectory(lwgps) + target_link_libraries(${PROJECT_NAME} lwgps) endif() - -# Set as executable -add_executable(${PROJECT_NAME}) - -# Add key executable block -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/dev/main.c - ${CMAKE_CURRENT_LIST_DIR}/examples/test_code.c -) - -# Add key include paths -target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/dev -) - -# Compilation definition information -target_compile_definitions(${PROJECT_NAME} PUBLIC - WIN32 - _DEBUG - CONSOLE - LWGPS_DEV -) - -# Compiler options -target_compile_options(${PROJECT_NAME} PRIVATE - -Wall - -Wextra - -Wpedantic -) - -# Add subdir with lwgps and link to project -add_subdirectory("lwgps" lwgps) -target_link_libraries(${PROJECT_NAME} lwgps) \ No newline at end of file From 50711840d9a5a368df82b23334157f8d87498859 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 30 Oct 2022 18:24:02 +0100 Subject: [PATCH 57/80] Update docs --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index 9afa481..f991c70 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -76,6 +76,7 @@ Table of contents :caption: Other projects :hidden: + LwBTN - Button manager LwDTC - DateTimeCron LwESP - ESP-AT library LwEVT - Event manager From e2caee2f3891401e89d73c6d91c29dfe2af79b8a Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 31 Oct 2022 10:24:55 +0100 Subject: [PATCH 58/80] Update vscode --- .vscode/launch.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index a53089a..c76ad22 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,15 +1,12 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { + /* GDB must in be in the PATH environment */ "name": "(Windows) Launch", "type": "cppdbg", "request": "launch", "program": "${command:cmake.launchTargetPath}", - "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", From a01ec6ddf63ebe88190ec1e9aac6b2762c57e66a Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 18 Dec 2022 12:30:03 +0100 Subject: [PATCH 59/80] fix(hdr): Apply header guard syntax LWxxx_module_HDR_H --- lwgps/src/include/lwgps/lwgps_opt.h | 6 +++--- lwgps/src/include/lwgps/lwgps_opts_template.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index ae25350..fc80c43 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -31,8 +31,8 @@ * Author: Tilen MAJERLE * Version: $2.1.0$ */ -#ifndef LWGPS_HDR_OPT_H -#define LWGPS_HDR_OPT_H +#ifndef LWGPS_OPT_HDR_H +#define LWGPS_OPT_HDR_H /* Uncomment to ignore user options (or set macro in compiler flags) */ /* #define LWGPS_IGNORE_USER_OPTS */ @@ -180,4 +180,4 @@ extern "C" { } #endif /* __cplusplus */ -#endif /* LWGPS_HDR_OPT_H */ +#endif /* LWGPS_OPT_HDR_H */ diff --git a/lwgps/src/include/lwgps/lwgps_opts_template.h b/lwgps/src/include/lwgps/lwgps_opts_template.h index 05b2eed..85c2110 100644 --- a/lwgps/src/include/lwgps/lwgps_opts_template.h +++ b/lwgps/src/include/lwgps/lwgps_opts_template.h @@ -31,8 +31,8 @@ * Author: Tilen MAJERLE * Version: v2.1.0 */ -#ifndef LWGPS_HDR_OPTS_H -#define LWGPS_HDR_OPTS_H +#ifndef LWGPS_OPTS_HDR_H +#define LWGPS_OPTS_HDR_H /* Rename this file to "lwgps_opts.h" for your application */ @@ -41,4 +41,4 @@ * copy & replace here settings you want to change values */ -#endif /* LWGPS_HDR_OPTS_H */ +#endif /* LWGPS_OPTS_HDR_H */ From 20f6f8826b15f519661ba470c4738013c2dcf9b0 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Wed, 21 Dec 2022 17:24:44 +0100 Subject: [PATCH 60/80] Update LwGPS to improve code size --- examples/example.c | 31 +++++++++++++------------ examples/test_code.c | 17 +++++++------- lwgps/src/include/lwgps/lwgps_opt.h | 9 ++++++++ lwgps/src/lwgps/lwgps.c | 35 +++++++++++++++++++++-------- 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/examples/example.c b/examples/example.c index 126fe61..45262af 100644 --- a/examples/example.c +++ b/examples/example.c @@ -12,22 +12,21 @@ lwgps_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 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"; int main() { diff --git a/examples/test_code.c b/examples/test_code.c index 5861d37..8c100e4 100644 --- a/examples/test_code.c +++ b/examples/test_code.c @@ -13,21 +13,20 @@ lwgps_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" - "$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" - ""; +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" + "$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" + ""; /** * \brief Run the test of raw input data */ void run_tests() { - lwgps_init(&hgps); /* Init GPS */ + lwgps_init(&hgps); /* Init GPS */ /* Process all input data */ lwgps_process(&hgps, gps_rx_data, strlen(gps_rx_data)); diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index fc80c43..7813bf0 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -167,6 +167,15 @@ extern "C" { #define LWGPS_CFG_CRC 1 #endif +/** + * \brief Enables `1` or disables `0` distance and bearing calculation + * + * \note When not enabled, corresponding function is disabled + */ +#ifndef LWESP_CFG_DISTANCE_BEARING +#define LWESP_CFG_DISTANCE_BEARING 1 +#endif + /* Guard against accidental parser breakage */ #if LWGPS_CFG_STATEMENT_PUBX_TIME && !LWGPS_CFG_STATEMENT_PUBX #error LWGPS_CFG_STATEMENT_PUBX must be enabled when enabling LWGPS_CFG_STATEMENT_PUBX_TIME diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index 64043b0..9ca67b7 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -31,10 +31,12 @@ * Author: Tilen MAJERLE * Version: v2.1.0 */ -#include #include #include #include "lwgps/lwgps.h" +#if LWESP_CFG_DISTANCE_BEARING +#include +#endif #define FLT(x) ((lwgps_float_t)(x)) #define D2R(x) FLT(FLT(x) * FLT(0.01745329251994)) /*!< Degrees to radians */ @@ -98,20 +100,31 @@ prv_parse_number(lwgps_t* gh, const char* t) { */ static lwgps_float_t prv_parse_float_number(lwgps_t* gh, const char* t) { - lwgps_float_t res; + lwgps_float_t value = (lwgps_float_t)0, power = (lwgps_float_t)1; + int sign = 1; if (t == NULL) { t = gh->p.term_str; } for (; t != NULL && *t == ' '; ++t) {} /* Strip leading spaces */ -#if LWGPS_CFG_DOUBLE - res = strtod(t, NULL); /* Parse string to double */ -#else /* LWGPS_CFG_DOUBLE */ - res = strtof(t, NULL); /* Parse string to float */ -#endif /* !LWGPS_CFG_DOUBLE */ - - return FLT(res); /* Return casted value, based on float size */ + if (*t == '-') { /* Check sign */ + sign = -1; + ++t; + } + while (CIN(*t)) { /* Convert main part */ + value = value * (lwgps_float_t)10 + CTN(*t); + ++t; + } + if (*t == '.') { /* Skip the dot character */ + ++t; + } + while (CIN(*t)) { /* Get the power */ + value = value * (lwgps_float_t)10 + CTN(*t); + power *= 10.0; + ++t; + } + return sign * value / power; } /** @@ -496,6 +509,8 @@ lwgps_process(lwgps_t* gh, const void* data, size_t len) { return 1; } +#if LWESP_CFG_DISTANCE_BEARING || __DOXYGEN__ + /** * \brief Calculate distance and bearing between `2` latitude and longitude coordinates * \param[in] las: Latitude start coordinate, in units of degrees @@ -574,6 +589,8 @@ lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, return 1; } +#endif /* LWESP_CFG_DISTANCE_BEARING || __DOXYGEN__ */ + /** * \brief Convert NMEA GPS speed (in knots = nautical mile per hour) to different speed format * \param[in] sik: Speed in knots, received from GPS NMEA statement From b5df27da228a9e0fb04cc21b22641b5fccae62bc Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Wed, 4 Jan 2023 21:14:08 +0100 Subject: [PATCH 61/80] Update license to 2023 --- LICENSE | 2 +- dev/lwgps_opts.h | 2 +- lwgps/src/include/lwgps/lwgps.h | 2 +- lwgps/src/include/lwgps/lwgps_opt.h | 2 +- lwgps/src/include/lwgps/lwgps_opts_template.h | 2 +- lwgps/src/lwgps/lwgps.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LICENSE b/LICENSE index 5625f63..3702ca4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Tilen MAJERLE +Copyright (c) 2023 Tilen MAJERLE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/dev/lwgps_opts.h b/dev/lwgps_opts.h index 0302114..be30c00 100644 --- a/dev/lwgps_opts.h +++ b/dev/lwgps_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2022 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/lwgps/src/include/lwgps/lwgps.h b/lwgps/src/include/lwgps/lwgps.h index f6c91f8..27c1763 100644 --- a/lwgps/src/include/lwgps/lwgps.h +++ b/lwgps/src/include/lwgps/lwgps.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2022 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index 7813bf0..5b0fc7a 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2022 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/lwgps/src/include/lwgps/lwgps_opts_template.h b/lwgps/src/include/lwgps/lwgps_opts_template.h index 85c2110..9785bb7 100644 --- a/lwgps/src/include/lwgps/lwgps_opts_template.h +++ b/lwgps/src/include/lwgps/lwgps_opts_template.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2022 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index 9ca67b7..c4128aa 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2022 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation From c094d2afcd86b71ed042d654cad26d4b3b18e26c Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 19 Feb 2023 12:42:43 +0100 Subject: [PATCH 62/80] Fix documentation --- docs/conf.py | 2 +- docs/get-started/index.rst | 2 +- docs/index.rst | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ac5817e..cfa27ad 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ # -- Project information ----------------------------------------------------- project = 'LwGPS' -copyright = '2022, Tilen MAJERLE' +copyright = '2023, Tilen MAJERLE' author = 'Tilen MAJERLE' # Try to get branch at which this is running diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index 24d7e8f..08bbfde 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -62,7 +62,7 @@ Next step is to add the library to the project, by means of source files to comp * Copy ``lwgps`` folder to your project, it contains library files * Add ``lwgps/src/include`` folder to `include path` of your toolchain. This is where `C/C++` compiler can find the files during compilation process. Usually using ``-I`` flag -* Add source files from ``lwgps/src/`` folder to toolchain build. These files are built by `C/C++` compiler +* Add source files from ``lwgps/src/`` folder to toolchain build. These files are built by `C/C++` compiler. CMake configuration comes with the library, allows users to include library in the project as **subdirectory** and **library**. * Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to project folder and rename it to ``lwgps_opts.h`` * Build the project diff --git a/docs/index.rst b/docs/index.rst index f991c70..856d2e1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -90,4 +90,5 @@ Table of contents LwRB - Ring buffer LwSHELL - Shell LwUTIL - Utility functions + LwWDG - RTOS task watchdog From fb53a0344969f8c586f2f9b730cf070b63903cff Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 23 Apr 2023 17:51:34 +0200 Subject: [PATCH 63/80] Remove entering/exiting debug messages --- lwgps/CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lwgps/CMakeLists.txt b/lwgps/CMakeLists.txt index 394b180..aca81b5 100644 --- a/lwgps/CMakeLists.txt +++ b/lwgps/CMakeLists.txt @@ -1,12 +1,6 @@ cmake_minimum_required(VERSION 3.22) -# Debug message -message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") - # Register library to the system add_library(lwgps INTERFACE) target_sources(lwgps INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/lwgps/lwgps.c) target_include_directories(lwgps INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include) - -# Debug message -message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") From cadce785f14f602ea88a766c6ca2faaa7fef3be5 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 7 May 2023 15:27:32 +0200 Subject: [PATCH 64/80] Change logo icon --- docs/static/images/1w_bit_byte.svg | 2 -- docs/static/images/1w_bit_byte.xml | 1 - docs/static/images/1w_od.svg | 2 -- docs/static/images/1w_od.xml | 1 - docs/static/images/1w_pp2od.svg | 2 -- docs/static/images/1w_pp2od.xml | 1 - docs/static/images/logo_tm.png | Bin 3338 -> 19296 bytes docs/static/images/logo_tm_full.png | Bin 17470 -> 23650 bytes 8 files changed, 9 deletions(-) delete mode 100644 docs/static/images/1w_bit_byte.svg delete mode 100644 docs/static/images/1w_bit_byte.xml delete mode 100644 docs/static/images/1w_od.svg delete mode 100644 docs/static/images/1w_od.xml delete mode 100644 docs/static/images/1w_pp2od.svg delete mode 100644 docs/static/images/1w_pp2od.xml diff --git a/docs/static/images/1w_bit_byte.svg b/docs/static/images/1w_bit_byte.svg deleted file mode 100644 index 775268c..0000000 --- a/docs/static/images/1w_bit_byte.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
ST
ST
b0
b0
b1
b1
b2
b2
b3
b3
b4
b4
b5
b5
b6
b6
b7
b7
SP
SP
ST
ST
b0
b0
b1
b1
b2
b2
b3
b3
b4
b4
b5
b5
b6
b6
b7
b7
SP
SP
Byte on UART level = bit on 1-Wire level
Timing is very important, HW takes care of it
Byte on UART level = bit on 1-Wire level<br>Timing is very important, HW takes care of it<br>
Byte on UART level = bit on 1-Wire level
Timing is very important, HW takes care of it
Byte on UART level = bit on 1-Wire level<br>Timing is very important, HW takes care of it<br>
Short time
Short time<br>
ST
ST
b0
b0
b1
b1
b2
b2
b3
b3
b4
b4
b5
b5
b6
b6
b7
b7
SP
SP
Byte on UART level = bit on 1-Wire level
Timing is very important, HW takes care of it
Byte on UART level = bit on 1-Wire level<br>Timing is very important, HW takes care of it<br>
Long time, some interrupt or different task is being executed
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/static/images/1w_bit_byte.xml b/docs/static/images/1w_bit_byte.xml deleted file mode 100644 index f7efe70..0000000 --- a/docs/static/images/1w_bit_byte.xml +++ /dev/null @@ -1 +0,0 @@ -7Ztfb5swFMU/TR4n2RgIPC5d1z5s0rR06rMDJlgBHDlOk+zTz4BpSM2kaupyq6vmITXXf8C/wwPn0MzYTX2803xbfle5qGYByY8z9mUWBDQkzP5pK6e+ktB5X1hrmbtB58JS/hauSFx1L3OxuxholKqM3F4WM9U0IjMXNa61OlwOK1R1edYtXwuvsMx45VcfZW5KV6Vxeu64F3JdulMngdvfimebtVb7xp1vFrCi+/TdNR/WchvdlTxXh1GJ3c7YjVbK9K36eCOqlu2ArZ/39S+9z9etRWNeMyHoJzzxau+2vnxwV2ZOA41uP6KdQWZscSilEcstz9reg9Xf1kpTV/aI2mbFV6JaPGO4UZXStqtRjR2/KFRjnNw0cMfDEMuKMWI/tu7vw23tSWgjjqOS29edULUw+mSHuF4W9TPcLRikDvnhLChzpXIkZehq3N1C6+eFzxhtw5Gcpso8qiuChGoMRzX0qVIkVFM4qrFPNUBClQZwWOc+VoYFawSHNfGxhliwJnBYUx9rhASrvV3BsA6Ps2OuMRauISBX6nOdY+E6B+Q6YQd+IOHKCCBX3xDgsVkJgeM6YQmwGK2QAnKNfK5YrFYYAnJFbLbCOSBXxG4rIoBcEdutiAFyRey3ohiO65CqY/RbUQrIFbHfigNAroj9VhwBcvX91uJkhK2oxn79+vzTui9SiafutWU3gKykGfrpp0epxXlEXNlrW6y0ba3b1oOsZbNuz7frkbTblvVWacMtr8BeH7l/tF+Gb0Q7JOPdcqpoxxl/QSSSv3jjxtiU4v9Lct8Kfkh+ffd/Xc19m7osrSKtDLIW7xN6IatqVM8jkeShre+MVhsx6kmsh4njN5LpFS/Dhzx3rFLyFir5phdN+JVAPjxMmF4s4VcC+fAwYXqxhF8JYFg79ZIRS/iVAoa1w7oYw68UMKxlE6YXS/iVAoa1zDe9aMIvSgDTWjbxb4dY0i9KAONaNvGaEUv8RQlgXssmDByW/IsSwMCW+Z7rIw25vh28ahrCfD/4TXUq9WFIK8pOtS0iGyO03m87wa0IJJdFIbqNt5rtNoO0K9HrLI4i2xurx7tU7mWkwkVSZFORSpwlYlW8Ub79CitFwwmt/yFTsYfnn4R0faPf3bDbPw== \ No newline at end of file diff --git a/docs/static/images/1w_od.svg b/docs/static/images/1w_od.svg deleted file mode 100644 index f501376..0000000 --- a/docs/static/images/1w_od.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
MCU OR
USB <-> UART
MCU OR<br>USB <-> UART
VCC
VCC<br>
1-WIRE
DEVICE
[Not supported by viewer]
1-WIRE
DEVICE
[Not supported by viewer]
1-WIRE
DEVICE
[Not supported by viewer]
TX PIN
TX PIN
RX PIN
RX PIN
\ No newline at end of file diff --git a/docs/static/images/1w_od.xml b/docs/static/images/1w_od.xml deleted file mode 100644 index 348ba5d..0000000 --- a/docs/static/images/1w_od.xml +++ /dev/null @@ -1 +0,0 @@ -7VpNc9owEP01HMnYkmXsYyBpy6Fpm5CU9tIRtjCaGIsRopD++sq2DJZlkuCYkHaSQ0a7+rL2vd2VNunAwXzzkePF7DMLSdwBVrjpwIsOAD2/J3+niodcgaCfKyJOw1xl7xQ39A9R45RyRUOy1MYJxmJBF7oyYElCAqHpMOdsrQ+bsljfdIEjYihuAhyb2u80FDOltV1/1/GJ0GimtvaAOu8cF4OtXLGc4ZCtSyp42YEDzpjIW/PNgMSp6Qqz5PM+7OndfhgniXjOhC+Mrn6Ovv2KRugD/0a7v4bTUVet8hvHK3Xgz4Nbqfhy3QFuLNftT7hsRWnr9qbfSfdw8Xwhxay3uxWzIbL/9vx6pA4sHgorrmdUkJsFDlJ5LXkix87EPJaSLZt4ucixm9INkZ/bn9I4HrCY8Ww6nHoBCQKpXwrO7kmpZ+IhB1nZzlVrFEcjXJBNSaWs85GwORH8QQ4pei2FlGIq8JS8LgFfjJmVMN8qsSJbtF17h4dsKEgOgMcz4DFMS5LwPOW5lBKWEN2wZEPFuNT+IdvWmfStJibOewovAI8ZfclWPCBP846EmveZ0JRMj2osX+g4ibGgv3WfrUND7fCVUfnFO+Q9pCEPLaQvkZ9HzSr7WGWhrbPvW0hgHhFhLJSRY3vs5nyxTX82CMPZKglTL7tIQX3CM0/iiNKhdEe0TUcEj7ChdTcsNmvuh4n8jHHmfKgQfzQ28QGOmPPtGYx5I55YdSDgVzBt6onAfV1PBH5LoVsxpgjejQiTzr7YqOmZ8KCEA6hUYchzgvxpqWT7Zz3kucByPd9FyAY6ISxwBm0LOo68sqXDvHaIZnvgVYkGzdh0NxiYtzeDfTIYC51y+wm0j3I4plEidYEkC5Gd/TTIU3l7PlcdcxqG6Ya1eUbPRC0kDtvX87jdMxNHHePAsRIHfEY+fjQKHDU5vNWY7zWM+Q56YqFjuyJ4R/tgtCFq6a796mjDljK8/jjrvT/Oqo8zHWcHtnQlNJh3bMIggzB29/vw+tJM1heXd8NBjd4g2KGFlRhPSNzHwX2UJd+CSYqcp3ntuRU/tsyk7dbQy20haUcArybjcLwZXlm3V5zeB5NJ97+FycCkBrm9MEHnjcHkvsNUA5NTzYqnhqn3wixpJrbHiimZsHvqZlLx1m2Kh/HwbVJnyYP/yS5dfktXbGhXK6VHu3TVsumlBfF/gU2nIgnstUWS6kLIP/NKP/6rUualhbhTUmZXIUnXVoYinEqbEJ4mKppEnXL55O2y68nHeeNX/knZVfMXl9FYyl+HVwbNzIpb+/WzF10ebKRHd1DU00oUcZBJkTbqZ/XWNSsq1/+NdaFzNOtKcfePBTnVd/+cAS//Ag== \ No newline at end of file diff --git a/docs/static/images/1w_pp2od.svg b/docs/static/images/1w_pp2od.svg deleted file mode 100644 index 087f696..0000000 --- a/docs/static/images/1w_pp2od.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
MCU OR
USB <-> UART
MCU OR<br>USB <-> UART
VCC
VCC<br>
1-WIRE
DEVICE
[Not supported by viewer]
1-WIRE
DEVICE
[Not supported by viewer]
TX PIN
TX PIN
RX PIN
RX PIN
\ No newline at end of file diff --git a/docs/static/images/1w_pp2od.xml b/docs/static/images/1w_pp2od.xml deleted file mode 100644 index 145373b..0000000 --- a/docs/static/images/1w_pp2od.xml +++ /dev/null @@ -1 +0,0 @@ -7Vxdd6I6FP01PraLBMLHY9V2pg8zd1Y7HWceKUTNGgQH01Hvr78BgkKigsiHt8WXkgMEOHvvk5ND6EAdLTafQns5/xK42BtAxd0M1PEAQqApKvsTWbaJxQRGYpiFxOUH7Q3P5F+cGBE3vhEXr3LH0SDwKFnmjU7g+9ihOZsdhsE6f9g08PIXXdozLBmeHduTrRPi0jl/CKTs7Z8xmc3TKwOF73m1nd+zMHjz+fUGUJ3Gv2T3wk774sev5rYbrDMm9X6gjsIgoMnWYjPCXuTa1GvJeQ9H9u7uO8Q+LXOCNRk++KOvD5//jP3J2Jj88TXnBqT9/LW9N5w+SHy7dJu6CPvuXeRp1vIDnxmHc7rwWAuwTbwh9CfbVm4Rb/2KWmx7SjxvFHhBGPeiTk0HOw6zr2gY/MaZPa8m0pDCzx5v+OlxY8sbyTkpQMx3w+QusSuhu/cH2HmZkRcHC0zDLTtkvYc5RXmeQTi1hdizKfmb797mbJvtuttd4VtA2IWhwoUBLU5wLgtgqvkuVsFb6GB+Vha3oo4QyndE7XCGqdQR28g89t4U0+IMiiBdYsiX0Qsz/PM0gLrHvDZ8DdnWLNp6eWbAMAfq9mLJmvHem10zPoTtf7l7+i6xbD0nFD8vbSdqr1msyfPMXi0T+U/JBruV6MWfA4cUb84lDT9BwAIanCwZTu0CRJZUO+MhAuUQOxseoyYBg6x8byGq5OLqOmU3HAuikIldCRqYSh57S9BhaUGr6HRHTQvaLGZMPK5FMoujb4E0O1Ei1MT4KksRnmBD7ULUlXc+kpZRqNnpkIu0WwOZOlR009IRAjDPEAPeqkBRNc2E8WFmRf0icUCGrepXl1O2H6ORPBZL7GNio3nKHSfQMcrZHpn5zOYwbmC2cxiJmLB0+o7vWBDXjS54MGjkw0oTUUCTo4B+gHGwsSigNTIcG/1wLA7HRh55TYS0rJxVkO9I1dodjnUkMQbcTB6f7mVFj+9/PI4O2CWGnZtLe/Yr9oa7CW1KJc7OTsZ3VciSwIFU+5Cy9caULc+DepyY7sC14VQivT0ZgeWgyVwRbjOpWdT8lcboqLFPteJWmmtVBaRMeE6iUmFc6So8q7owyRHz7tLh2RKmXYbQUdPh2foAdOqKJZpWE0ukjqB1a2Z+VqucMeQM/ftP1v72+FXijpyUX1mKDZAgQBNJAT71fisptgEl7z69G+/u0p6uvGvJ3j0v3rU5S+ms0qAJqInl3dK1BKEjKS1qOFJZao/22WhXr/yibiu/1qXFiQ+BtjDxrK5tsc7ftrblwkKPdnEArkvbYkdNoy2XJ06h7Xj2akWcDwi4iJNZ19AtdtQ04HW9+E1fESWV5vTd0+G3R1dWggaKcU1cqj5UFJGyYS4Bpc8MSsAt1rQq54FGt3kgUPrUoALcVYtTkrrFjhqH+7zcoIf7MnUX8aZxuEtkBjQktj87WufKYO+SEDuUBFFtjLkgQqJGPtT69l8F5dYAAeU4OS4qngFw6XLaD6G0oqlS5cCqtqy0dIVRD/cpuIWFk9WzZHEFZssFFQD6aun5cFcfR8XF1m1nyaCfFJWA26hrDixOilpXdz8pqqDuymO3qO6W66UA9AXTcoiLQFUumIrUabvIBfqKKXNCt0v0rbpGiyJWNk6mEssM38ck27y6SXaJJXn/gw+YBL92/gETSK/WJ0DnDIe1JUBtFy/gpbNZGbz3t0JVQqm2FaptV4VhP5stsWy96GOgql8V1Qc3a+7/aURy+P4fc6j3/wE= \ No newline at end of file diff --git a/docs/static/images/logo_tm.png b/docs/static/images/logo_tm.png index 51ef5776e1fa5f334f4e94495669feed77eca0f7..4b0be88e5a0db1405c599f9579ab1d31eed57ebf 100644 GIT binary patch literal 19296 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 K&pB!x^#1_MR`ELk literal 3338 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 diff --git a/docs/static/images/logo_tm_full.png b/docs/static/images/logo_tm_full.png index 3e5ba6544885a88614d35bf27e0cbcdefa1286c6..970d835160ed6f11b74be4fcba1e9662a2960c5c 100644 GIT binary patch literal 23650 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 XM6dma(=Bf(!_rdIQ!RgB`|5uHl2YG# From 1c073b5727a57b84d507c0132b01093196d57880 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 7 May 2023 15:44:04 +0200 Subject: [PATCH 65/80] Fix requirements.txt file to avoid liburl3 failure --- docs/requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 834b1bb..bf1bde0 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,8 @@ +sphinx>=3.5.1 breathe>=4.9.1 -colorama +urllib3==1.26.15 docutils==0.16 -sphinx>=3.5.1 +colorama sphinx_rtd_theme>=1.0.0 sphinx-tabs sphinxcontrib-svg2pdfconverter From 8c7155e7dedbeaa85b98798dafa678fc49896c56 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 7 May 2023 15:49:33 +0200 Subject: [PATCH 66/80] Change contribution text --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 12d8d5d..3c44103 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Platform independent GPS NMEA parser for embedded systems. Fresh contributions are always welcome. Simple instructions to proceed:: 1. Fork Github repository -2. Respect [C style & coding rules](https://github.com/MaJerle/c-code-style) used by the library +2. Follow [C style & coding rules](https://github.com/MaJerle/c-code-style) already used in the project 3. Create a pull request to develop branch with new features or bug fixes Alternatively you may: From ad95983790b0ff4625b097286cc603b6de5055f7 Mon Sep 17 00:00:00 2001 From: Sirio Balmelli Date: Wed, 10 May 2023 16:51:11 +0200 Subject: [PATCH 67/80] prv_parse_float_number: remove implicit promotion to double The exact GCC error being fixed: lwgps/lwgps/src/lwgps/lwgps.c:124:15: error: implicit conversion from 'lwgps_float_t' {aka 'float'} to 'double' to match other operand of binary expression [-Werror=double-promotion] Signed-off-by: Sirio Balmelli --- lwgps/src/lwgps/lwgps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index c4128aa..04d89d5 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -121,7 +121,7 @@ prv_parse_float_number(lwgps_t* gh, const char* t) { } while (CIN(*t)) { /* Get the power */ value = value * (lwgps_float_t)10 + CTN(*t); - power *= 10.0; + power *= (lwgps_float_t)10.0; ++t; } return sign * value / power; From 5e700bdb4b10c0e207262a7a1f9b6003c1a19510 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 28 May 2023 12:04:52 +0200 Subject: [PATCH 68/80] Apply new .clang-format --- .clang-format | 4 +- lwgps/src/include/lwgps/lwgps_opt.h | 2 +- lwgps/src/lwgps/lwgps.c | 146 ++++++++-------------------- 3 files changed, 46 insertions(+), 106 deletions(-) diff --git a/.clang-format b/.clang-format index 1fad350..0227352 100644 --- a/.clang-format +++ b/.clang-format @@ -16,14 +16,14 @@ AlignConsecutiveBitFields: AlignConsecutiveDeclarations: None AlignEscapedNewlines: Right AlignOperands: Align -SortIncludes: false +SortIncludes: true InsertBraces: true # Control statements must have curly brackets AlignTrailingComments: true AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortEnumsOnASingleLine: true AllowShortBlocksOnASingleLine: Empty -AllowShortCaseLabelsOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortLambdasOnASingleLine: All AllowShortIfStatementsOnASingleLine: Never diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index 5b0fc7a..9484a46 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -173,7 +173,7 @@ extern "C" { * \note When not enabled, corresponding function is disabled */ #ifndef LWESP_CFG_DISTANCE_BEARING -#define LWESP_CFG_DISTANCE_BEARING 1 +#define LWESP_CFG_DISTANCE_BEARING 1 #endif /* Guard against accidental parser breakage */ diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index 04d89d5..9e83a19 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -207,37 +207,20 @@ prv_parse_term(lwgps_t* gh) { gh->p.data.gga.longitude = -gh->p.data.gga.longitude; } break; - case 6: /* Fix status */ - gh->p.data.gga.fix = (uint8_t)prv_parse_number(gh, NULL); - break; - case 7: /* Satellites in use */ - gh->p.data.gga.sats_in_use = (uint8_t)prv_parse_number(gh, NULL); - break; - case 9: /* Altitude */ - gh->p.data.gga.altitude = prv_parse_float_number(gh, NULL); - break; - case 11: /* Altitude above ellipsoid */ - gh->p.data.gga.geo_sep = prv_parse_float_number(gh, NULL); - break; - default: - break; + case 6: /* Fix status */ gh->p.data.gga.fix = (uint8_t)prv_parse_number(gh, NULL); break; + case 7: /* Satellites in use */ gh->p.data.gga.sats_in_use = (uint8_t)prv_parse_number(gh, NULL); break; + case 9: /* Altitude */ gh->p.data.gga.altitude = prv_parse_float_number(gh, NULL); break; + case 11: /* Altitude above ellipsoid */ gh->p.data.gga.geo_sep = prv_parse_float_number(gh, NULL); break; + default: break; } #endif /* LWGPS_CFG_STATEMENT_GPGGA */ #if LWGPS_CFG_STATEMENT_GPGSA } else if (gh->p.stat == STAT_GSA) { /* Process GPGSA statement */ switch (gh->p.term_num) { - case 2: /* Process fix mode */ - gh->p.data.gsa.fix_mode = (uint8_t)prv_parse_number(gh, NULL); - break; - case 15: /* Process PDOP */ - gh->p.data.gsa.dop_p = prv_parse_float_number(gh, NULL); - break; - case 16: /* Process HDOP */ - gh->p.data.gsa.dop_h = prv_parse_float_number(gh, NULL); - break; - case 17: /* Process VDOP */ - gh->p.data.gsa.dop_v = prv_parse_float_number(gh, NULL); - break; + case 2: /* Process fix mode */ gh->p.data.gsa.fix_mode = (uint8_t)prv_parse_number(gh, NULL); break; + case 15: /* Process PDOP */ gh->p.data.gsa.dop_p = prv_parse_float_number(gh, NULL); break; + case 16: /* Process HDOP */ gh->p.data.gsa.dop_h = prv_parse_float_number(gh, NULL); break; + case 17: /* Process VDOP */ gh->p.data.gsa.dop_v = prv_parse_float_number(gh, NULL); break; default: /* Parse satellite IDs */ if (gh->p.term_num >= 3 && gh->p.term_num <= 14) { @@ -265,20 +248,11 @@ prv_parse_term(lwgps_t* gh) { if (index < sizeof(gh->sats_in_view_desc) / sizeof(gh->sats_in_view_desc[0])) { value = (uint16_t)prv_parse_number(gh, NULL); /* Parse number as integer */ switch (term_num & 0x03) { - case 0: - gh->sats_in_view_desc[index].num = value; - break; - case 1: - gh->sats_in_view_desc[index].elevation = value; - break; - case 2: - gh->sats_in_view_desc[index].azimuth = value; - break; - case 3: - gh->sats_in_view_desc[index].snr = value; - break; - default: - break; + case 0: gh->sats_in_view_desc[index].num = value; break; + case 1: gh->sats_in_view_desc[index].elevation = value; break; + case 2: gh->sats_in_view_desc[index].azimuth = value; break; + case 3: gh->sats_in_view_desc[index].snr = value; break; + default: break; } } } @@ -289,15 +263,9 @@ prv_parse_term(lwgps_t* gh) { #if LWGPS_CFG_STATEMENT_GPRMC } else if (gh->p.stat == STAT_RMC) { /* Process GPRMC statement */ switch (gh->p.term_num) { - case 2: /* Process valid status */ - gh->p.data.rmc.is_valid = (gh->p.term_str[0] == 'A'); - break; - case 7: /* Process ground speed in knots */ - gh->p.data.rmc.speed = prv_parse_float_number(gh, NULL); - break; - case 8: /* Process true ground coarse */ - gh->p.data.rmc.course = prv_parse_float_number(gh, NULL); - break; + case 2: /* Process valid status */ gh->p.data.rmc.is_valid = (gh->p.term_str[0] == 'A'); break; + case 7: /* Process ground speed in knots */ gh->p.data.rmc.speed = prv_parse_float_number(gh, NULL); break; + case 8: /* Process true ground coarse */ gh->p.data.rmc.course = prv_parse_float_number(gh, NULL); break; case 9: /* Process date */ gh->p.data.rmc.date = (uint8_t)(10 * CTN(gh->p.term_str[0]) + CTN(gh->p.term_str[1])); gh->p.data.rmc.month = (uint8_t)(10 * CTN(gh->p.term_str[2]) + CTN(gh->p.term_str[3])); @@ -311,8 +279,7 @@ prv_parse_term(lwgps_t* gh) { gh->p.data.rmc.variation = -gh->p.data.rmc.variation; } break; - default: - break; + default: break; } #endif /* LWGPS_CFG_STATEMENT_GPRMC */ #if LWGPS_CFG_STATEMENT_PUBX @@ -333,12 +300,8 @@ prv_parse_term(lwgps_t* gh) { 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 = prv_parse_float_number(gh, NULL); - break; - case 5: /* Process UTC WeekNumber */ - gh->p.data.time.utc_wk = prv_parse_number(gh, NULL); - break; + case 4: /* Process UTC TimeOfWeek */ gh->p.data.time.utc_tow = prv_parse_float_number(gh, NULL); break; + case 5: /* Process UTC WeekNumber */ gh->p.data.time.utc_wk = prv_parse_number(gh, NULL); break; case 6: /* Process UTC leap seconds */ /* * Accomodate a 2- or 3-digit leap second count @@ -351,17 +314,10 @@ prv_parse_term(lwgps_t* gh) { 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 = prv_parse_number(gh, NULL); - break; - case 8: /* Process clock drift */ - gh->p.data.time.clk_drift = prv_parse_float_number(gh, NULL); - break; - case 9: /* Process time pulse granularity */ - gh->p.data.time.tp_gran = prv_parse_number(gh, NULL); - break; - default: - break; + case 7: /* Process clock bias */ gh->p.data.time.clk_bias = prv_parse_number(gh, NULL); break; + case 8: /* Process clock drift */ gh->p.data.time.clk_drift = prv_parse_float_number(gh, NULL); break; + case 9: /* Process time pulse granularity */ gh->p.data.time.tp_gran = prv_parse_number(gh, NULL); break; + default: break; } #endif /* LWGPS_CFG_STATEMENT_PUBX_TIME */ #endif /* LWGPS_CFG_STATEMENT_PUBX */ @@ -600,40 +556,24 @@ lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, lwgps_float_t lwgps_to_speed(lwgps_float_t sik, lwgps_speed_t ts) { switch (ts) { - case lwgps_speed_kps: - return FLT(sik * FLT(0.000514)); - case lwgps_speed_kph: - return FLT(sik * FLT(1.852)); - case lwgps_speed_mps: - return FLT(sik * FLT(0.5144)); - case lwgps_speed_mpm: - return FLT(sik * FLT(30.87)); - - case lwgps_speed_mips: - return FLT(sik * FLT(0.0003197)); - case lwgps_speed_mph: - return FLT(sik * FLT(1.151)); - case lwgps_speed_fps: - return FLT(sik * FLT(1.688)); - case lwgps_speed_fpm: - return FLT(sik * FLT(101.3)); - - case lwgps_speed_mpk: - return FLT(sik * FLT(32.4)); - case lwgps_speed_spk: - return FLT(sik * FLT(1944.0)); - case lwgps_speed_sp100m: - return FLT(sik * FLT(194.4)); - case lwgps_speed_mipm: - return FLT(sik * FLT(52.14)); - case lwgps_speed_spm: - return FLT(sik * FLT(3128.0)); - case lwgps_speed_sp100y: - return FLT(sik * FLT(177.7)); - - case lwgps_speed_smph: - return FLT(sik * FLT(1.0)); - default: - return 0; + case lwgps_speed_kps: return FLT(sik * FLT(0.000514)); + case lwgps_speed_kph: return FLT(sik * FLT(1.852)); + case lwgps_speed_mps: return FLT(sik * FLT(0.5144)); + case lwgps_speed_mpm: return FLT(sik * FLT(30.87)); + + case lwgps_speed_mips: return FLT(sik * FLT(0.0003197)); + case lwgps_speed_mph: return FLT(sik * FLT(1.151)); + case lwgps_speed_fps: return FLT(sik * FLT(1.688)); + case lwgps_speed_fpm: return FLT(sik * FLT(101.3)); + + case lwgps_speed_mpk: return FLT(sik * FLT(32.4)); + case lwgps_speed_spk: return FLT(sik * FLT(1944.0)); + case lwgps_speed_sp100m: return FLT(sik * FLT(194.4)); + case lwgps_speed_mipm: return FLT(sik * FLT(52.14)); + case lwgps_speed_spm: return FLT(sik * FLT(3128.0)); + case lwgps_speed_sp100y: return FLT(sik * FLT(177.7)); + + case lwgps_speed_smph: return FLT(sik * FLT(1.0)); + default: return 0; } } From f55d220474aecf80e0a0a0a6ce73f9f964cff725 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 11 Jun 2023 10:33:21 +0200 Subject: [PATCH 69/80] Add first C++ wrapper template --- CMakeLists.txt | 2 +- dev/{main.c => main.cpp} | 5 ++- lwgps/src/include/lwgps/lwgps.hpp | 59 +++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) rename dev/{main.c => main.cpp} (91%) create mode 100644 lwgps/src/include/lwgps/lwgps.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f713b72..22e70fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ else() # Add key executable block target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/dev/main.c + ${CMAKE_CURRENT_LIST_DIR}/dev/main.cpp ${CMAKE_CURRENT_LIST_DIR}/examples/test_code.c ) diff --git a/dev/main.c b/dev/main.cpp similarity index 91% rename from dev/main.c rename to dev/main.cpp index d1adec5..a6d5cb6 100644 --- a/dev/main.c +++ b/dev/main.cpp @@ -6,9 +6,12 @@ #include #include #include "lwgps/lwgps.h" +#include "lwgps/lwgps.hpp" /* External function */ -extern void run_tests(); +extern "C" void run_tests(); + +Lwgps::Lwgps gps; int main() { diff --git a/lwgps/src/include/lwgps/lwgps.hpp b/lwgps/src/include/lwgps/lwgps.hpp new file mode 100644 index 0000000..44eedb3 --- /dev/null +++ b/lwgps/src/include/lwgps/lwgps.hpp @@ -0,0 +1,59 @@ +/** + * \file lwgps.hpp + * \brief C++ wrapper for LwGPS + */ + +/* + * Copyright (c) 2023 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGPS - Lightweight GPS NMEA parser library. + * + * Author: Tilen MAJERLE + * Version: v2.1.0 + */ +#ifndef LWGPS_HDR_HPP +#define LWGPS_HDR_HPP + +#include "lwgps/lwgps.h" + +namespace Lwgps { +class Lwgps { + private: + lwgps_t m_hgps; + + public: + Lwgps(const Lwgps& other) = delete; /* No copy constructor */ + Lwgps& operator=(const Lwgps& other) = delete; /* No copy assignment */ + Lwgps(const Lwgps&& other) = delete; /* No move constructor */ + Lwgps& operator=(Lwgps&& other) = delete; /* No move assignment */ + + Lwgps() { /* Constructor */ + lwgps_init(&m_hgps); + } + + ~Lwgps() { /* Destructor */ + } +}; +}; // namespace Lwgps + +#endif /* LWGPS_HDR_HPP */ From be23dc167dcab9e27f4b81c053670c4c8991d7a2 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 11 Jun 2023 10:40:13 +0200 Subject: [PATCH 70/80] Deprecate lowercase lwgps_speed_xxx macros --- lwgps/src/include/lwgps/lwgps.h | 46 ++++++++++++++++++++++----------- lwgps/src/lwgps/lwgps.c | 33 +++++++++++------------ 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/lwgps/src/include/lwgps/lwgps.h b/lwgps/src/include/lwgps/lwgps.h index 27c1763..f960462 100644 --- a/lwgps/src/include/lwgps/lwgps.h +++ b/lwgps/src/include/lwgps/lwgps.h @@ -230,29 +230,45 @@ typedef struct { */ typedef enum { /* Metric values */ - lwgps_speed_kps, /*!< Kilometers per second */ - lwgps_speed_kph, /*!< Kilometers per hour */ - lwgps_speed_mps, /*!< Meters per second */ - lwgps_speed_mpm, /*!< Meters per minute */ + LWGPS_SPEED_KPS, /*!< Kilometers per second */ + LWGPS_SPEED_KPH, /*!< Kilometers per hour */ + LWGPS_SPEED_MPS, /*!< Meters per second */ + LWGPS_SPEED_MPM, /*!< Meters per minute */ /* Imperial values */ - lwgps_speed_mips, /*!< Miles per second */ - lwgps_speed_mph, /*!< Miles per hour */ - lwgps_speed_fps, /*!< Foots per second */ - lwgps_speed_fpm, /*!< Foots per minute */ + LWGPS_SPEED_MIPS, /*!< Miles per second */ + LWGPS_SPEED_MPH, /*!< Miles per hour */ + LWGPS_SPEED_FPS, /*!< Foots per second */ + LWGPS_SPEED_FPM, /*!< Foots per minute */ /* Optimized for runners/joggers */ - lwgps_speed_mpk, /*!< Minutes per kilometer */ - lwgps_speed_spk, /*!< Seconds per kilometer */ - lwgps_speed_sp100m, /*!< Seconds per 100 meters */ - lwgps_speed_mipm, /*!< Minutes per mile */ - lwgps_speed_spm, /*!< Seconds per mile */ - lwgps_speed_sp100y, /*!< Seconds per 100 yards */ + LWGPS_SPEED_MPK, /*!< Minutes per kilometer */ + LWGPS_SPEED_SPK, /*!< Seconds per kilometer */ + LWGPS_SPEED_SP100M, /*!< Seconds per 100 meters */ + LWGPS_SPEED_MIPM, /*!< Minutes per mile */ + LWGPS_SPEED_SPM, /*!< Seconds per mile */ + LWGPS_SPEED_SP100Y, /*!< Seconds per 100 yards */ /* Nautical values */ - lwgps_speed_smph, /*!< Sea miles per hour */ + LWGPS_SPEED_SMPH, /*!< Sea miles per hour */ } lwgps_speed_t; +#define lwgps_speed_kps LWGPS_SPEED_KPS /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_kph LWGPS_SPEED_KPH /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_mps LWGPS_SPEED_MPS /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_mpm LWGPS_SPEED_MPM /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_mips LWGPS_SPEED_MIPS /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_mph LWGPS_SPEED_MPH /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_fps LWGPS_SPEED_FPS /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_fpm LWGPS_SPEED_FPM /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_mpk LWGPS_SPEED_MPK /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_spk LWGPS_SPEED_SPK /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_sp100m LWGPS_SPEED_SP100M /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_mipm LWGPS_SPEED_MIPM /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_spm LWGPS_SPEED_SPM /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_sp100y LWGPS_SPEED_SP100Y /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ +#define lwgps_speed_smph LWGPS_SPEED_SMPH /*!< Backward compatibility. \deprecated Use \ref lwgps_speed_t instead */ + /** * \brief Signature for caller-suplied callback function from gps_process * \param[in] res: statement type of recently parsed statement diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index 9e83a19..2107ac1 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -556,24 +556,21 @@ lwgps_distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, lwgps_float_t lwgps_to_speed(lwgps_float_t sik, lwgps_speed_t ts) { switch (ts) { - case lwgps_speed_kps: return FLT(sik * FLT(0.000514)); - case lwgps_speed_kph: return FLT(sik * FLT(1.852)); - case lwgps_speed_mps: return FLT(sik * FLT(0.5144)); - case lwgps_speed_mpm: return FLT(sik * FLT(30.87)); - - case lwgps_speed_mips: return FLT(sik * FLT(0.0003197)); - case lwgps_speed_mph: return FLT(sik * FLT(1.151)); - case lwgps_speed_fps: return FLT(sik * FLT(1.688)); - case lwgps_speed_fpm: return FLT(sik * FLT(101.3)); - - case lwgps_speed_mpk: return FLT(sik * FLT(32.4)); - case lwgps_speed_spk: return FLT(sik * FLT(1944.0)); - case lwgps_speed_sp100m: return FLT(sik * FLT(194.4)); - case lwgps_speed_mipm: return FLT(sik * FLT(52.14)); - case lwgps_speed_spm: return FLT(sik * FLT(3128.0)); - case lwgps_speed_sp100y: return FLT(sik * FLT(177.7)); - - case lwgps_speed_smph: return FLT(sik * FLT(1.0)); + case LWGPS_SPEED_KPS: return FLT(sik * FLT(0.000514)); + case LWGPS_SPEED_KPH: return FLT(sik * FLT(1.852)); + case LWGPS_SPEED_MPS: return FLT(sik * FLT(0.5144)); + case LWGPS_SPEED_MPM: return FLT(sik * FLT(30.87)); + case LWGPS_SPEED_MIPS: return FLT(sik * FLT(0.0003197)); + case LWGPS_SPEED_MPH: return FLT(sik * FLT(1.151)); + case LWGPS_SPEED_FPS: return FLT(sik * FLT(1.688)); + case LWGPS_SPEED_FPM: return FLT(sik * FLT(101.3)); + case LWGPS_SPEED_MPK: return FLT(sik * FLT(32.4)); + case LWGPS_SPEED_SPK: return FLT(sik * FLT(1944.0)); + case LWGPS_SPEED_SP100M: return FLT(sik * FLT(194.4)); + case LWGPS_SPEED_MIPM: return FLT(sik * FLT(52.14)); + case LWGPS_SPEED_SPM: return FLT(sik * FLT(3128.0)); + case LWGPS_SPEED_SP100Y: return FLT(sik * FLT(177.7)); + case LWGPS_SPEED_SMPH: return FLT(sik * FLT(1.0)); default: return 0; } } From b1710b965b69cbd328596687af3ae00d873468fb Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 11 Jun 2023 11:46:42 +0200 Subject: [PATCH 71/80] Add simple time-based docs --- CHANGELOG.md | 1 + docs/user-manual/index.rst | 1 + docs/user-manual/nmea-update-packet.rst | 57 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 docs/user-manual/nmea-update-packet.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index 1196c9b..50d9bfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Split CMakeLists.txt files between library and executable - Change license year to 2022 - Add `.clang-format` draft +- Deprecate lowercase `lwgps_speed_xxx` enumeration. Temporary implement macro to keep backward compatibility. Will be removed in next major release ## v2.1.0 diff --git a/docs/user-manual/index.rst b/docs/user-manual/index.rst index 48a1e64..b8549aa 100644 --- a/docs/user-manual/index.rst +++ b/docs/user-manual/index.rst @@ -9,4 +9,5 @@ User manual how-it-works float-double thread-safety + nmea-update-packet tests \ No newline at end of file diff --git a/docs/user-manual/nmea-update-packet.rst b/docs/user-manual/nmea-update-packet.rst new file mode 100644 index 0000000..ace4a68 --- /dev/null +++ b/docs/user-manual/nmea-update-packet.rst @@ -0,0 +1,57 @@ +.. _nmea_packet_update: + +NMEA data refresh +================= + +LwGPS is designed to parse standard NMEA output from GPS module. + +.. tip:: + You can read more about `NMEA 0183 here `_. + +GPS module outputs several NMEA statements periodically, for instance once a second. In rare cases, outputs can be even every `100ms`. +The common *problem* we try to solve is what happens if application tries to access GPS parsed data, while library processed only part of +new NMEA statement. + +Depending on the application requirements, it is necessary to make sure data used by the application are all from the single NMEA output packet, +and not split between different ones. Below are ``2`` examples of several statements GPS module will output every second. + +First statement at any given time: +``$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F`` +``$GPGGA,183730,3907.356,N,12102.482,W,1,05,1.6,646.4,M,-24.1,M,,*75`` +``$GPGSA,A,3,02,,,07,,09,24,26,,,,,1.6,1.6,1.0*3D`` +``$GPGSV,2,1,08,02,43,088,38,04,42,145,00,05,11,291,00,07,60,043,35*71`` +``$GPGSV,2,2,08,08,02,145,00,09,46,303,47,24,16,178,32,26,18,231,43*77`` + +New statement after one second: +``$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F`` +``$GPGGA,183730,3907.356,N,12102.482,W,1,05,1.6,646.4,M,-24.1,M,,*75`` +``$GPGSA,A,3,02,,,07,,09,24,26,,,,,1.6,1.6,1.0*3D`` +``$GPGSV,2,1,08,02,43,088,38,04,42,145,00,05,11,291,00,07,60,043,35*71`` +``$GPGSV,2,2,08,08,02,145,00,09,46,303,47,24,16,178,32,26,18,231,43*77`` + +If application manages to check GPS parsed data after first packet has been processed and second didn't arrive yet, there is no issue. +Application parsed data are all belonging to single packet, at specific time. + +But what would happen if application starts using GPS data while ``GPGGA`` packet is being received for second time? + +* Application has new ``GPRMC`` information, from new packet +* Application still keeps ``GPGGA``, ``GPGSA`` and ``GPGSV`` data from old packets + +This could be a major issue for some applications. Time, speed and position do not match anymore. + +Common approach +*************** + +A common approach to this is to have a source of time in the application. +A set of timeouts could determine if packet has just started, or has just been completed and is now fully filled with new data. + +An algorithm would be, assuming GPS sends packet data every ``1`` second: + +* When character comes, if time of previous character is greater than maximum time between ``2`` characters (let's say ``10ms``, even if this is a lot), this is probably start of new packet. +* If new time is ``>10ms`` since last received character, it was probably the last character. +* Application can now use new data +* Application goes to *wait new packet mode* +* Go back to step nr.1 + +.. toctree:: + :maxdepth: 2 From 7c6df5188f075ac49251b4604a80cd79d6deca97 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Thu, 20 Jul 2023 22:15:58 +0200 Subject: [PATCH 72/80] Update link for new LwCELL, add C11 standard note --- README.md | 2 +- docs/index.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3c44103..04d682c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Platform independent GPS NMEA parser for embedded systems. ## Features -* Written in ANSI C99 +* Written in C (C11) * Platform independent, easy to use * Built-in support for 4 GPS statements * ``GPGGA`` or ``GNGGA``: GPS fix data diff --git a/docs/index.rst b/docs/index.rst index 856d2e1..4b9f5c7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,7 +16,7 @@ LwGPS is lightweight, platform independent library to parse NMEA statements from Features ^^^^^^^^ -* Written in ANSI C99 +* Written in C (C11) * Platform independent, easy to use * Built-in support for 4 GPS statements @@ -81,7 +81,7 @@ Table of contents LwESP - ESP-AT library LwEVT - Event manager LwGPS - GPS NMEA parser - LwGSM - GSM-AT library + LwCELL - Cellular modem host AT library LwJSON - JSON parser LwMEM - Memory manager LwOW - OneWire with UART From 2a6addcf8e5293f7cb966424d3aafc2bbc0d6a98 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 27 Aug 2023 19:48:33 +0200 Subject: [PATCH 73/80] Fix double colon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04d682c..dff226d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Platform independent GPS NMEA parser for embedded systems. ## Contribute -Fresh contributions are always welcome. Simple instructions to proceed:: +Fresh contributions are always welcome. Simple instructions to proceed: 1. Fork Github repository 2. Follow [C style & coding rules](https://github.com/MaJerle/c-code-style) already used in the project From 216190bd1b26a5fcf4ac98b806377be1da45ac66 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 28 Aug 2023 21:42:55 +0200 Subject: [PATCH 74/80] Add readthedocs YAML file --- .readthedocs.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..dd64b05 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,18 @@ +version: 2 +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Python configuration +python: + install: + - requirements: docs/requirements.txt + +formats: + - pdf + - epub From cb62fec234ef36ebe4e0f756f0b4fd463385b384 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 03:25:41 +0000 Subject: [PATCH 75/80] Bump urllib3 from 1.26.15 to 1.26.17 in /docs Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.15 to 1.26.17. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.15...1.26.17) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index bf1bde0..27e9780 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ sphinx>=3.5.1 breathe>=4.9.1 -urllib3==1.26.15 +urllib3==1.26.17 docutils==0.16 colorama sphinx_rtd_theme>=1.0.0 From 335b5c0631b9e243fe3f8f69e55b23622e749d8f Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 11 Oct 2023 21:09:09 -0400 Subject: [PATCH 76/80] Add CodeQL Workflow for Code Security Analysis Add CodeQL Workflow for Code Security Analysis This pull request introduces a CodeQL workflow to enhance the security analysis of our repository. CodeQL is a powerful static analysis tool that helps identify and mitigate security vulnerabilities in our codebase. By integrating this workflow into our GitHub Actions, we can proactively identify and address potential issues before they become security threats. We added a new CodeQL workflow file (.github/workflows/codeql.yml) that - Runs on every push and pull request to the main branch. - Excludes queries with a high false positive rate or low-severity findings. - Does not display results for third-party code, focusing only on our own codebase. Testing: To validate the functionality of this workflow, we have run several test scans on the codebase and reviewed the results. The workflow successfully compiles the project, identifies issues, and provides actionable insights while reducing noise by excluding certain queries and third-party code. Deployment: Once this pull request is merged, the CodeQL workflow will be active and automatically run on every push and pull request to the main branch. To view the results of these code scans, please follow these steps: 1. Under the repository name, click on the Security tab. 2. In the left sidebar, click Code scanning alerts. Additional Information: - You can further customize the workflow to adapt to your specific needs by modifying the workflow file. - For more information on CodeQL and how to interpret its results, refer to the GitHub documentation and the CodeQL documentation. Signed-off-by: Brian --- .github/workflows/codeql-buildscript.sh | 5 + .github/workflows/codeql.yml | 123 ++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 .github/workflows/codeql-buildscript.sh create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql-buildscript.sh b/.github/workflows/codeql-buildscript.sh new file mode 100644 index 0000000..322ae93 --- /dev/null +++ b/.github/workflows/codeql-buildscript.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +cd examples +mkdir build && cd build && cmake .. +make diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..eaa9599 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,123 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "main", "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "main", "master" ] + schedule: + - cron: '28 21 * * 0' + +jobs: + analyze: + name: Analyze + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-20.04' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: recursive + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + queries: security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + #- name: Autobuild + # uses: github/codeql-action/autobuild@v2 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + - run: | + ./.github/workflows/codeql-buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" + upload: false + id: step1 + + # Filter out rules with low severity or high false positve rate + # Also filter out warnings in third-party code + - name: Filter out unwanted errors and warnings + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -**:cpp/path-injection + -**:cpp/world-writable-file-creation + -**:cpp/poorly-documented-function + -**:cpp/potentially-dangerous-function + -**:cpp/use-of-goto + -**:cpp/integer-multiplication-cast-to-long + -**:cpp/comparison-with-wider-type + -**:cpp/leap-year/* + -**:cpp/ambiguously-signed-bit-field + -**:cpp/suspicious-pointer-scaling + -**:cpp/suspicious-pointer-scaling-void + -**:cpp/unsigned-comparison-zero + -**/third*party/** + -**/3rd*party/** + -**/external/** + input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif + output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: ${{ steps.step1.outputs.sarif-output }} + category: "/language:${{matrix.language}}" + + - name: Archive CodeQL results + uses: actions/upload-artifact@v3 + with: + name: codeql-results + path: ${{ steps.step1.outputs.sarif-output }} + retention-days: 5 \ No newline at end of file From d06eef1ba999f850a3de848bf8f9dcb6d33f67a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 01:16:47 +0000 Subject: [PATCH 77/80] Bump urllib3 from 1.26.17 to 1.26.18 in /docs Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.17 to 1.26.18. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.17...1.26.18) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 27e9780..d70b1a4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ sphinx>=3.5.1 breathe>=4.9.1 -urllib3==1.26.17 +urllib3==1.26.18 docutils==0.16 colorama sphinx_rtd_theme>=1.0.0 From 653d75241d87b20213d4add05caac178a4e2961d Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 18 Oct 2023 17:17:06 -0400 Subject: [PATCH 78/80] Add CodeQL Workflow for Code Security Analysis Add CodeQL Workflow for Code Security Analysis This pull request introduces a CodeQL workflow to enhance the security analysis of our repository. CodeQL is a powerful static analysis tool that helps identify and mitigate security vulnerabilities in our codebase. By integrating this workflow into our GitHub Actions, we can proactively identify and address potential issues before they become security threats. We added a new CodeQL workflow file (.github/workflows/codeql.yml) that - Runs on every pull request (functionality to run on every push to main branches is included as a comment for convenience). - Runs daily. - Excludes queries with a high false positive rate or low-severity findings. - Does not display results for git submodules, focusing only on our own codebase. Testing: To validate the functionality of this workflow, we have run several test scans on the codebase and reviewed the results. The workflow successfully compiles the project, identifies issues, and provides actionable insights while reducing noise by excluding certain queries and third-party code. Deployment: Once this pull request is merged, the CodeQL workflow will be active and automatically run on every push and pull request to the main branch. To view the results of these code scans, please follow these steps: 1. Under the repository name, click on the Security tab. 2. In the left sidebar, click Code scanning alerts. Additional Information: - You can further customize the workflow to adapt to your specific needs by modifying the workflow file. - For more information on CodeQL and how to interpret its results, refer to the GitHub documentation and the CodeQL documentation (https://codeql.github.com/ and https://codeql.github.com/docs/). Signed-off-by: Brian --- .github/workflows/codeql.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index eaa9599..3ef873f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -14,11 +14,10 @@ name: "CodeQL" on: push: branches: [ "main", "master" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "main", "master" ] schedule: - - cron: '28 21 * * 0' + - cron: '0 0 * * *' + pull_request: + branches: '*' jobs: analyze: @@ -103,21 +102,25 @@ jobs: -**:cpp/suspicious-pointer-scaling -**:cpp/suspicious-pointer-scaling-void -**:cpp/unsigned-comparison-zero - -**/third*party/** - -**/3rd*party/** - -**/external/** + -**/cmake*/Modules/** input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif - - name: Upload SARIF + - name: Upload CodeQL results to code scanning uses: github/codeql-action/upload-sarif@v2 with: sarif_file: ${{ steps.step1.outputs.sarif-output }} category: "/language:${{matrix.language}}" - - name: Archive CodeQL results + - name: Upload CodeQL results as an artifact + if: success() || failure() uses: actions/upload-artifact@v3 with: name: codeql-results path: ${{ steps.step1.outputs.sarif-output }} - retention-days: 5 \ No newline at end of file + retention-days: 5 + + - name: Fail if an error is found + run: | + ./.github/workflows/fail_on_error.py \ + ${{ steps.step1.outputs.sarif-output }}/cpp.sarif From d18f6cce2731600c574327c05f4d91a99a3c2de4 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 20 Oct 2023 01:14:32 -0400 Subject: [PATCH 79/80] Add CodeQL Workflow for Code Security Analysis Add CodeQL Workflow for Code Security Analysis This pull request introduces a CodeQL workflow to enhance the security analysis of our repository. CodeQL is a powerful static analysis tool that helps identify and mitigate security vulnerabilities in our codebase. By integrating this workflow into our GitHub Actions, we can proactively identify and address potential issues before they become security threats. We added a new CodeQL workflow file (.github/workflows/codeql.yml) that - Runs on every pull request (functionality to run on every push to main branches is included as a comment for convenience). - Runs daily. - Excludes queries with a high false positive rate or low-severity findings. - Does not display results for git submodules, focusing only on our own codebase. Testing: To validate the functionality of this workflow, we have run several test scans on the codebase and reviewed the results. The workflow successfully compiles the project, identifies issues, and provides actionable insights while reducing noise by excluding certain queries and third-party code. Deployment: Once this pull request is merged, the CodeQL workflow will be active and automatically run on every push and pull request to the main branch. To view the results of these code scans, please follow these steps: 1. Under the repository name, click on the Security tab. 2. In the left sidebar, click Code scanning alerts. Additional Information: - You can further customize the workflow to adapt to your specific needs by modifying the workflow file. - For more information on CodeQL and how to interpret its results, refer to the GitHub documentation and the CodeQL documentation (https://codeql.github.com/ and https://codeql.github.com/docs/). Signed-off-by: Brian --- .github/workflows/fail_on_error.py | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 .github/workflows/fail_on_error.py diff --git a/.github/workflows/fail_on_error.py b/.github/workflows/fail_on_error.py new file mode 100755 index 0000000..2979174 --- /dev/null +++ b/.github/workflows/fail_on_error.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import json +import sys + +# Return whether SARIF file contains error-level results +def codeql_sarif_contain_error(filename): + with open(filename, 'r') as f: + s = json.load(f) + + for run in s.get('runs', []): + rules_metadata = run['tool']['driver']['rules'] + if not rules_metadata: + rules_metadata = run['tool']['extensions'][0]['rules'] + + for res in run.get('results', []): + if 'ruleIndex' in res: + rule_index = res['ruleIndex'] + elif 'rule' in res and 'index' in res['rule']: + rule_index = res['rule']['index'] + else: + continue + try: + rule_level = rules_metadata[rule_index]['defaultConfiguration']['level'] + except IndexError as e: + print(e, rule_index, len(rules_metadata)) + else: + if rule_level == 'error': + return True + return False + +if __name__ == "__main__": + if codeql_sarif_contain_error(sys.argv[1]): + sys.exit(1) From fead51b2dbace01cd7f8a16cf0a3d6c86bf33592 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 28 Oct 2023 12:06:24 +0200 Subject: [PATCH 80/80] C++ improvement, version v2.2.0 --- CHANGELOG.md | 7 +- dev/lwgps_opts.h | 2 +- dev/main.cpp | 6 +- examples/test_code.c | 2 +- library.json | 64 +++++++++--------- lwgps/src/include/lwgps/lwgps.h | 2 +- lwgps/src/include/lwgps/lwgps.hpp | 67 ++++++++++++++++++- lwgps/src/include/lwgps/lwgps_opt.h | 2 +- lwgps/src/include/lwgps/lwgps_opts_template.h | 2 +- lwgps/src/lwgps/lwgps.c | 2 +- 10 files changed, 112 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50d9bfe..b5cb779 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,13 @@ ## Develop -- Split CMakeLists.txt files between library and executable -- Change license year to 2022 +## v2.2.0 + +- Split `CMakeLists.txt` files between library and executable +- Change license year to `2023` - Add `.clang-format` draft - Deprecate lowercase `lwgps_speed_xxx` enumeration. Temporary implement macro to keep backward compatibility. Will be removed in next major release +- Improve `C++` port ## v2.1.0 diff --git a/dev/lwgps_opts.h b/dev/lwgps_opts.h index be30c00..5c056d2 100644 --- a/dev/lwgps_opts.h +++ b/dev/lwgps_opts.h @@ -29,7 +29,7 @@ * This file is part of LwGPS - Lightweight GPS NMEA parser library. * * Author: Tilen MAJERLE - * Version: $2.1.0$ + * Version: $2.2.0$ */ #ifndef LWGPS_HDR_OPTS_H #define LWGPS_HDR_OPTS_H diff --git a/dev/main.cpp b/dev/main.cpp index a6d5cb6..f1360b1 100644 --- a/dev/main.cpp +++ b/dev/main.cpp @@ -2,9 +2,9 @@ * This example uses direct processing function, * to process dummy NMEA data from GPS receiver */ -#include -#include #include +#include +#include #include "lwgps/lwgps.h" #include "lwgps/lwgps.hpp" @@ -28,6 +28,8 @@ main() { printf("Distance: %lf meters\r\n", (double)distance); printf("Bearing: %lf degrees\r\n", (double)bearing); + gps.distance_bearing(0, 0, 0, 0, 0, 0); + return 0; } diff --git a/examples/test_code.c b/examples/test_code.c index 8c100e4..ce77607 100644 --- a/examples/test_code.c +++ b/examples/test_code.c @@ -2,8 +2,8 @@ * This example uses direct processing function, * to process dummy NMEA data from GPS receiver */ -#include #include +#include #include "lwgps/lwgps.h" #include "test_common.h" diff --git a/library.json b/library.json index 10f5ab2..5048387 100644 --- a/library.json +++ b/library.json @@ -1,35 +1,33 @@ { - "name": "LwGPS", - "version": "2.1.0", - "description": "Lightweight GPS NMEA statement parser for embedded systems", - "keywords": "lwgps, global, position, satellite, glonass, gps, altitude, embedded, platform, independent", - "repository": { - "type": "git", - "url": "https://github.com/MaJerle/lwgps.git" - }, - "authors": [ - { - "name": "Tilen Majerle", - "email": "tilen@majerle.eu", - "url": "https://majerle.eu" - } - ], - "license": "MIT", - "homepage": "https://github.com/MaJerle/lwgps", - "dependencies": { - - }, - "frameworks": "*", - "platforms": "*", - "export": { - "exclude": [ - ".github", - "dev", - "docs", - "**/.vs", - "**/Debug", - "build", - "**/build" - ] - } + "name": "LwGPS", + "version": "2.2.0", + "description": "Lightweight GPS NMEA statement parser for embedded systems", + "keywords": "lwgps, global, position, satellite, glonass, gps, altitude, embedded, platform, independent", + "repository": { + "type": "git", + "url": "https://github.com/MaJerle/lwgps.git" + }, + "authors": [ + { + "name": "Tilen Majerle", + "email": "tilen@majerle.eu", + "url": "https://majerle.eu" + } + ], + "license": "MIT", + "homepage": "https://github.com/MaJerle/lwgps", + "dependencies": {}, + "frameworks": "*", + "platforms": "*", + "export": { + "exclude": [ + ".github", + "dev", + "docs", + "**/.vs", + "**/Debug", + "build", + "**/build" + ] + } } \ No newline at end of file diff --git a/lwgps/src/include/lwgps/lwgps.h b/lwgps/src/include/lwgps/lwgps.h index f960462..4b27999 100644 --- a/lwgps/src/include/lwgps/lwgps.h +++ b/lwgps/src/include/lwgps/lwgps.h @@ -29,7 +29,7 @@ * This file is part of LwGPS - Lightweight GPS NMEA parser library. * * Author: Tilen MAJERLE - * Version: v2.1.0 + * Version: v2.2.0 */ #ifndef LWGPS_HDR_H #define LWGPS_HDR_H diff --git a/lwgps/src/include/lwgps/lwgps.hpp b/lwgps/src/include/lwgps/lwgps.hpp index 44eedb3..daaef5c 100644 --- a/lwgps/src/include/lwgps/lwgps.hpp +++ b/lwgps/src/include/lwgps/lwgps.hpp @@ -29,7 +29,7 @@ * This file is part of LwGPS - Lightweight GPS NMEA parser library. * * Author: Tilen MAJERLE - * Version: v2.1.0 + * Version: v2.2.0 */ #ifndef LWGPS_HDR_HPP #define LWGPS_HDR_HPP @@ -41,6 +41,10 @@ class Lwgps { private: lwgps_t m_hgps; +#if LWGPS_CFG_STATUS || __DOXYGEN__ + lwgps_process_fn m_procfn; +#endif /* LWGPS_CFG_STATUS || __DOXYGEN__ */ + public: Lwgps(const Lwgps& other) = delete; /* No copy constructor */ Lwgps& operator=(const Lwgps& other) = delete; /* No copy assignment */ @@ -49,6 +53,67 @@ class Lwgps { Lwgps() { /* Constructor */ lwgps_init(&m_hgps); +#if LWGPS_CFG_STATUS + m_procfn = nullptr; +#endif /* LWGPS_CFG_STATUS */ + } + +#if LWGPS_CFG_STATUS || __DOXYGEN__ + /** + * \brief Set processing callback function + * + * \param procfn + */ + void + set_process_fn(lwgps_process_fn procfn) { + this->m_procfn = procfn; + } +#endif /* LWGPS_CFG_STATUS || __DOXYGEN__ */ + + /** + * \brief Process NMEA data from GPS receiver + * \param[in] data: Received data + * \param[in] len: Number of bytes to process + * \return `1` on success, `0` otherwise + */ + uint8_t + process(const void* data, size_t len) { + return lwgps_process(&m_hgps, data, len +#if LWGPS_CFG_STATUS + , + m_procfn +#endif /* LWGPS_CFG_STATUS */ + ); + } + +#if LWESP_CFG_DISTANCE_BEARING || __DOXYGEN__ + + /** + * \brief Calculate distance and bearing between `2` latitude and longitude coordinates + * \param[in] las: Latitude start coordinate, in units of degrees + * \param[in] los: Longitude start coordinate, in units of degrees + * \param[in] lae: Latitude end coordinate, in units of degrees + * \param[in] loe: Longitude end coordinate, in units of degrees + * \param[out] d: Pointer to output distance in units of meters + * \param[out] b: Pointer to output bearing between start and end coordinate in relation to north in units of degrees + * \return `1` on success, `0` otherwise + */ + static uint8_t + distance_bearing(lwgps_float_t las, lwgps_float_t los, lwgps_float_t lae, lwgps_float_t loe, lwgps_float_t* d, + lwgps_float_t* b) { + return lwgps_distance_bearing(las, los, lae, loe, d, b); + } +#endif /* LWESP_CFG_DISTANCE_BEARING || __DOXYGEN__ */ + + /** + * \brief Convert NMEA GPS speed (in knots = nautical mile per hour) to different speed format + * \param[in] sik: Speed in knots, received from GPS NMEA statement + * \param[in] ts: Target speed to convert to from knots + * \return Speed calculated from knots + */ + static lwgps_float_t + to_speed(lwgps_float_t sik, lwgps_speed_t ts) { + return lwgps_to_speed(sik, ts); } ~Lwgps() { /* Destructor */ diff --git a/lwgps/src/include/lwgps/lwgps_opt.h b/lwgps/src/include/lwgps/lwgps_opt.h index 9484a46..e37e6a2 100644 --- a/lwgps/src/include/lwgps/lwgps_opt.h +++ b/lwgps/src/include/lwgps/lwgps_opt.h @@ -29,7 +29,7 @@ * This file is part of LwGPS - Lightweight GPS NMEA parser library. * * Author: Tilen MAJERLE - * Version: $2.1.0$ + * Version: $2.2.0$ */ #ifndef LWGPS_OPT_HDR_H #define LWGPS_OPT_HDR_H diff --git a/lwgps/src/include/lwgps/lwgps_opts_template.h b/lwgps/src/include/lwgps/lwgps_opts_template.h index 9785bb7..ff17d9c 100644 --- a/lwgps/src/include/lwgps/lwgps_opts_template.h +++ b/lwgps/src/include/lwgps/lwgps_opts_template.h @@ -29,7 +29,7 @@ * This file is part of LwGPS - Lightweight GPS NMEA parser library. * * Author: Tilen MAJERLE - * Version: v2.1.0 + * Version: v2.2.0 */ #ifndef LWGPS_OPTS_HDR_H #define LWGPS_OPTS_HDR_H diff --git a/lwgps/src/lwgps/lwgps.c b/lwgps/src/lwgps/lwgps.c index 2107ac1..491dcdc 100644 --- a/lwgps/src/lwgps/lwgps.c +++ b/lwgps/src/lwgps/lwgps.c @@ -29,7 +29,7 @@ * This file is part of LwGPS - Lightweight GPS NMEA parser library. * * Author: Tilen MAJERLE - * Version: v2.1.0 + * Version: v2.2.0 */ #include #include