Skip to content

Commit bf0b774

Browse files
committed
gnss: rtk: Add basic integration
This patch incorporates the basic RTK API as well as a basic client integration (Serial) as a way to receive and publish the RTK data. Specifically, this patch includes: - RTK API additions. - RTCM3 frame decoding. - Add CRC API for RTCM3 frame checksum calculation. - Unit testsuite for RTCM3 frame decoding. - Serial client to receive and publish RTK data corrections. - GNSS RTK sample with simple base-station script over serial and Zephyr app displaying data-corrections applied. Signed-off-by: Luis Ubieda <luisf@croxel.com>
1 parent 51a79ba commit bf0b774

File tree

37 files changed

+819
-6
lines changed

37 files changed

+819
-6
lines changed

boards/lilygo/ttgo_tbeam/doc/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ The following sample applications will work out of the box with this board:
180180

181181
* :zephyr:code-sample:`lora-send`
182182
* :zephyr:code-sample:`lora-receive`
183-
* :zephyr:code-sample:`gnss`
183+
* :zephyr:code-sample:`gnss-basic`
184184
* :zephyr:code-sample:`wifi-shell`
185185
* :zephyr:code-sample:`character-frame-buffer`
186186
* :zephyr:code-sample:`blinky`

cmake/linker_script/common/common-rom.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,7 @@ endif()
259259
if(CONFIG_GNSS_SATELLITES)
260260
zephyr_iterable_section(NAME gnss_satellites_callback KVMA RAM_REGION GROUP RODATA_REGION)
261261
endif()
262+
263+
if(CONFIG_GNSS_RTK)
264+
zephyr_iterable_section(NAME gnss_rtk_data_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
265+
endif()

include/zephyr/gnss/rtk/decoder.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2025 Croxel Inc.
3+
* Copyright (c) 2025 CogniPilot Foundation
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#ifndef ZEPHYR_INCLUDE_GNSS_RTK_DECODER_H_
9+
#define ZEPHYR_INCLUDE_GNSS_RTK_DECODER_H_
10+
11+
#include <stdint.h>
12+
#include <stddef.h>
13+
14+
/**
15+
* @brief Get an RTK frame from buffer
16+
*
17+
* Used by RTK clients to extract frames from a data-buffer.
18+
*
19+
* @param[in] buf Buffer holding encoded data.
20+
* @param[in] buf_len Buffer length.
21+
* @param[out] data Pointer to the decoded frame.
22+
* @param[out] data_len Length of the decoded frame
23+
*
24+
* @return Zero if successful.
25+
* @return -ENOENT if no frames have been decoded successfully.
26+
* @return -EAGAIN if there's an incomplete frame starting at the data pointer.
27+
* @return Other negative error code if decoding failed.
28+
*/
29+
int gnss_rtk_decoder_frame_get(uint8_t *buf, size_t buf_len,
30+
uint8_t **data, size_t *data_len);
31+
32+
#endif /* ZEPHYR_INCLUDE_GNSS_RTK_DECODER_H_ */

include/zephyr/gnss/rtk/rtk.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2023 Trackunit Corporation
3+
* Copyright (c) 2025 Croxel Inc.
4+
* Copyright (c) 2025 CogniPilot Foundation
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#ifndef ZEPHYR_INCLUDE_GNSS_RTK_RTK_H_
10+
#define ZEPHYR_INCLUDE_GNSS_RTK_RTK_H_
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
#include <stdint.h>
17+
#include <stddef.h>
18+
19+
struct gnss_rtk_data {
20+
const uint8_t *data;
21+
size_t len;
22+
};
23+
24+
typedef void (*gnss_rtk_data_callback_t)(const struct device *dev,
25+
const struct gnss_rtk_data *data);
26+
27+
struct gnss_rtk_data_callback {
28+
const struct device *dev;
29+
gnss_rtk_data_callback_t callback;
30+
};
31+
32+
#if CONFIG_GNSS_RTK
33+
#define GNSS_RTK_DATA_CALLBACK_DEFINE(_dev, _callback) \
34+
static const STRUCT_SECTION_ITERABLE(gnss_rtk_data_callback, \
35+
_gnss_rtk_data_callback__##_callback) = { \
36+
.dev = _dev, \
37+
.callback = _callback, \
38+
}
39+
#else
40+
#define GNSS_RTK_DATA_CALLBACK_DEFINE(_dev, _callback)
41+
#endif
42+
43+
#ifdef __cplusplus
44+
}
45+
#endif
46+
47+
48+
#endif /* ZEPHYR_INCLUDE_GNSS_RTK_RTK_H_ */

include/zephyr/gnss/rtk/rtk_publish.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (c) 2025 Croxel Inc.
3+
* Copyright (c) 2025 CogniPilot Foundation
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#ifndef ZEPHYR_INCLUDE_GNSS_RTK_PUBLISH_H_
9+
#define ZEPHYR_INCLUDE_GNSS_RTK_PUBLISH_H_
10+
11+
#include <stdint.h>
12+
#include <stddef.h>
13+
#include <zephyr/gnss/rtk/rtk.h>
14+
15+
/* Internal function used by RTK clients to publish data-correction. */
16+
void gnss_rtk_publish_data(const struct gnss_rtk_data *data);
17+
18+
#endif /* ZEPHYR_INCLUDE_GNSS_RTK_PUBLISH_H_ */

include/zephyr/linker/common-rom/common-rom-misc.ld

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,7 @@
6868
#if defined(CONFIG_GNSS_SATELLITES)
6969
ITERABLE_SECTION_ROM(gnss_satellites_callback, Z_LINK_ITERABLE_SUBALIGN)
7070
#endif
71+
72+
#if defined(CONFIG_GNSS_RTK)
73+
ITERABLE_SECTION_ROM(gnss_rtk_data_callback, Z_LINK_ITERABLE_SUBALIGN)
74+
#endif

include/zephyr/sys/crc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,17 @@ uint32_t crc24_pgp(const uint8_t *data, size_t len);
391391
*/
392392
uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len);
393393

394+
/**
395+
* @brief Calculate an RTCM3 CRC24Q frame checksum
396+
*
397+
* @param[in] data RTCM3 Frame
398+
* @param[in] len Frame length in bytes.
399+
*
400+
* @return 0 if the data-frame contains a checksum and it matches.
401+
* @return Result if data-frame does not contain checksum.
402+
*/
403+
uint32_t crc24q_rtcm3(const uint8_t *data, size_t len);
404+
394405
/**
395406
* @brief Compute a CRC checksum, in a generic way.
396407
*

lib/crc/crc24_sw.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
/*
22
* Copyright (C) 2024 BayLibre.
3+
* Copyright (c) 2020 Brandon Owen.
4+
* Copyright (c) 2025 Croxel Inc.
5+
* Copyright (c) 2025 CogniPilot Foundation.
36
*
47
* SPDX-License-Identifier: Apache-2.0
58
*/
@@ -30,3 +33,62 @@ uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len)
3033

3134
return crc;
3235
}
36+
37+
/** This code is originally extracted from https://github.com/go-gnss/rtcm,
38+
* licensed as Apache-2.0.
39+
*/
40+
41+
static const uint32_t crc24q[] = {
42+
0x000000, 0x864cfb, 0x8ad50d, 0x0c99f6, 0x93e6e1, 0x15aa1a, 0x1933ec, 0x9f7f17,
43+
0xa18139, 0x27cdc2, 0x2b5434, 0xad18cf, 0x3267d8, 0xb42b23, 0xb8b2d5, 0x3efe2e,
44+
0xc54e89, 0x430272, 0x4f9b84, 0xc9d77f, 0x56a868, 0xd0e493, 0xdc7d65, 0x5a319e,
45+
0x64cfb0, 0xe2834b, 0xee1abd, 0x685646, 0xf72951, 0x7165aa, 0x7dfc5c, 0xfbb0a7,
46+
0x0cd1e9, 0x8a9d12, 0x8604e4, 0x00481f, 0x9f3708, 0x197bf3, 0x15e205, 0x93aefe,
47+
0xad50d0, 0x2b1c2b, 0x2785dd, 0xa1c926, 0x3eb631, 0xb8faca, 0xb4633c, 0x322fc7,
48+
0xc99f60, 0x4fd39b, 0x434a6d, 0xc50696, 0x5a7981, 0xdc357a, 0xd0ac8c, 0x56e077,
49+
0x681e59, 0xee52a2, 0xe2cb54, 0x6487af, 0xfbf8b8, 0x7db443, 0x712db5, 0xf7614e,
50+
0x19a3d2, 0x9fef29, 0x9376df, 0x153a24, 0x8a4533, 0x0c09c8, 0x00903e, 0x86dcc5,
51+
0xb822eb, 0x3e6e10, 0x32f7e6, 0xb4bb1d, 0x2bc40a, 0xad88f1, 0xa11107, 0x275dfc,
52+
0xdced5b, 0x5aa1a0, 0x563856, 0xd074ad, 0x4f0bba, 0xc94741, 0xc5deb7, 0x43924c,
53+
0x7d6c62, 0xfb2099, 0xf7b96f, 0x71f594, 0xee8a83, 0x68c678, 0x645f8e, 0xe21375,
54+
0x15723b, 0x933ec0, 0x9fa736, 0x19ebcd, 0x8694da, 0x00d821, 0x0c41d7, 0x8a0d2c,
55+
0xb4f302, 0x32bff9, 0x3e260f, 0xb86af4, 0x2715e3, 0xa15918, 0xadc0ee, 0x2b8c15,
56+
0xd03cb2, 0x567049, 0x5ae9bf, 0xdca544, 0x43da53, 0xc596a8, 0xc90f5e, 0x4f43a5,
57+
0x71bd8b, 0xf7f170, 0xfb6886, 0x7d247d, 0xe25b6a, 0x641791, 0x688e67, 0xeec29c,
58+
0x3347a4, 0xb50b5f, 0xb992a9, 0x3fde52, 0xa0a145, 0x26edbe, 0x2a7448, 0xac38b3,
59+
0x92c69d, 0x148a66, 0x181390, 0x9e5f6b, 0x01207c, 0x876c87, 0x8bf571, 0x0db98a,
60+
0xf6092d, 0x7045d6, 0x7cdc20, 0xfa90db, 0x65efcc, 0xe3a337, 0xef3ac1, 0x69763a,
61+
0x578814, 0xd1c4ef, 0xdd5d19, 0x5b11e2, 0xc46ef5, 0x42220e, 0x4ebbf8, 0xc8f703,
62+
0x3f964d, 0xb9dab6, 0xb54340, 0x330fbb, 0xac70ac, 0x2a3c57, 0x26a5a1, 0xa0e95a,
63+
0x9e1774, 0x185b8f, 0x14c279, 0x928e82, 0x0df195, 0x8bbd6e, 0x872498, 0x016863,
64+
0xfad8c4, 0x7c943f, 0x700dc9, 0xf64132, 0x693e25, 0xef72de, 0xe3eb28, 0x65a7d3,
65+
0x5b59fd, 0xdd1506, 0xd18cf0, 0x57c00b, 0xc8bf1c, 0x4ef3e7, 0x426a11, 0xc426ea,
66+
0x2ae476, 0xaca88d, 0xa0317b, 0x267d80, 0xb90297, 0x3f4e6c, 0x33d79a, 0xb59b61,
67+
0x8b654f, 0x0d29b4, 0x01b042, 0x87fcb9, 0x1883ae, 0x9ecf55, 0x9256a3, 0x141a58,
68+
0xefaaff, 0x69e604, 0x657ff2, 0xe33309, 0x7c4c1e, 0xfa00e5, 0xf69913, 0x70d5e8,
69+
0x4e2bc6, 0xc8673d, 0xc4fecb, 0x42b230, 0xddcd27, 0x5b81dc, 0x57182a, 0xd154d1,
70+
0x26359f, 0xa07964, 0xace092, 0x2aac69, 0xb5d37e, 0x339f85, 0x3f0673, 0xb94a88,
71+
0x87b4a6, 0x01f85d, 0x0d61ab, 0x8b2d50, 0x145247, 0x921ebc, 0x9e874a, 0x18cbb1,
72+
0xe37b16, 0x6537ed, 0x69ae1b, 0xefe2e0, 0x709df7, 0xf6d10c, 0xfa48fa, 0x7c0401,
73+
0x42fa2f, 0xc4b6d4, 0xc82f22, 0x4e63d9, 0xd11cce, 0x575035, 0x5bc9c3, 0xdd8538
74+
};
75+
76+
/**
77+
* @brief Calculate RTCM3 frame checksum
78+
*
79+
* @param[in] data RTCM3 Frame
80+
* @param[in] size Frame length in bytes.
81+
*
82+
* @retval 0 if the data-frame contains a checksum and it matches.
83+
* @retval Result if data-frame does not contain checksum.
84+
*/
85+
uint32_t crc24q_rtcm3(const uint8_t *data, size_t len)
86+
{
87+
uint32_t crc = 0;
88+
89+
for (uint32_t i = 0; i < len; ++i) {
90+
crc = ((crc << 8) & 0xFFFFFF) ^ crc24q[data[i] ^ (crc >> 16)];
91+
}
92+
93+
return crc;
94+
}

samples/drivers/gnss/basic/README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
.. zephyr:code-sample:: gnss
2-
:name: GNSS
1+
.. zephyr:code-sample:: gnss-basic
2+
:name: GNSS Basic
33
:relevant-api: gnss_interface navigation
44

55
Connect to a GNSS device to obtain time, navigation data, and satellite information.

samples/drivers/gnss/index.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.. zephyr:code-sample-category:: gnss
2+
:name: gnss
3+
:show-listing:
4+
5+
These samples demonstrate how to use the GNSS driver API.

0 commit comments

Comments
 (0)