1 /*
2 * Copyright (c) 2023 Trackunit Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file gnss.h
9 * @brief Public GNSS API.
10 */
11
12 #ifndef ZEPHYR_INCLUDE_DRIVERS_GNSS_H_
13 #define ZEPHYR_INCLUDE_DRIVERS_GNSS_H_
14
15 /**
16 * @brief GNSS Interface
17 * @defgroup gnss_interface GNSS Interface
18 * @since 3.6
19 * @version 0.1.0
20 * @ingroup io_interfaces
21 * @{
22 */
23
24 #include <zephyr/kernel.h>
25 #include <zephyr/types.h>
26 #include <zephyr/device.h>
27 #include <zephyr/data/navigation.h>
28 #include <errno.h>
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 /** GNSS PPS modes */
35 enum gnss_pps_mode {
36 /** PPS output disabled */
37 GNSS_PPS_MODE_DISABLED = 0,
38 /** PPS output always enabled */
39 GNSS_PPS_MODE_ENABLED = 1,
40 /** PPS output enabled from first lock */
41 GNSS_PPS_MODE_ENABLED_AFTER_LOCK = 2,
42 /** PPS output enabled while locked */
43 GNSS_PPS_MODE_ENABLED_WHILE_LOCKED = 3
44 };
45
46 /** API for setting fix rate */
47 typedef int (*gnss_set_fix_rate_t)(const struct device *dev, uint32_t fix_interval_ms);
48
49 /** API for getting fix rate */
50 typedef int (*gnss_get_fix_rate_t)(const struct device *dev, uint32_t *fix_interval_ms);
51
52 /** GNSS navigation modes */
53 enum gnss_navigation_mode {
54 /** Dynamics have no impact on tracking */
55 GNSS_NAVIGATION_MODE_ZERO_DYNAMICS = 0,
56 /** Low dynamics have higher impact on tracking */
57 GNSS_NAVIGATION_MODE_LOW_DYNAMICS = 1,
58 /** Low and high dynamics have equal impact on tracking */
59 GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS = 2,
60 /** High dynamics have higher impact on tracking */
61 GNSS_NAVIGATION_MODE_HIGH_DYNAMICS = 3
62 };
63
64 /** API for setting navigation mode */
65 typedef int (*gnss_set_navigation_mode_t)(const struct device *dev,
66 enum gnss_navigation_mode mode);
67
68 /** API for getting navigation mode */
69 typedef int (*gnss_get_navigation_mode_t)(const struct device *dev,
70 enum gnss_navigation_mode *mode);
71
72 /** Systems contained in gnss_systems_t */
73 enum gnss_system {
74 /** Global Positioning System (GPS) */
75 GNSS_SYSTEM_GPS = BIT(0),
76 /** GLObal NAvigation Satellite System (GLONASS) */
77 GNSS_SYSTEM_GLONASS = BIT(1),
78 /** Galileo */
79 GNSS_SYSTEM_GALILEO = BIT(2),
80 /** BeiDou Navigation Satellite System */
81 GNSS_SYSTEM_BEIDOU = BIT(3),
82 /** Quasi-Zenith Satellite System (QZSS) */
83 GNSS_SYSTEM_QZSS = BIT(4),
84 /** Indian Regional Navigation Satellite System (IRNSS) */
85 GNSS_SYSTEM_IRNSS = BIT(5),
86 /** Satellite-Based Augmentation System (SBAS) */
87 GNSS_SYSTEM_SBAS = BIT(6),
88 /** Indoor Messaging System (IMES) */
89 GNSS_SYSTEM_IMES = BIT(7),
90 };
91
92 /** Type storing bitmask of GNSS systems */
93 typedef uint32_t gnss_systems_t;
94
95 /** API for enabling systems */
96 typedef int (*gnss_set_enabled_systems_t)(const struct device *dev, gnss_systems_t systems);
97
98 /** API for getting enabled systems */
99 typedef int (*gnss_get_enabled_systems_t)(const struct device *dev, gnss_systems_t *systems);
100
101 /** API for getting enabled systems */
102 typedef int (*gnss_get_supported_systems_t)(const struct device *dev, gnss_systems_t *systems);
103
104 /** API for getting timestamp of last PPS pulse */
105 typedef int (*gnss_get_latest_timepulse_t)(const struct device *dev, k_ticks_t *timestamp);
106
107 /** GNSS fix status */
108 enum gnss_fix_status {
109 /** No GNSS fix acquired */
110 GNSS_FIX_STATUS_NO_FIX = 0,
111 /** GNSS fix acquired */
112 GNSS_FIX_STATUS_GNSS_FIX = 1,
113 /** Differential GNSS fix acquired */
114 GNSS_FIX_STATUS_DGNSS_FIX = 2,
115 /** Estimated fix acquired */
116 GNSS_FIX_STATUS_ESTIMATED_FIX = 3,
117 };
118
119 /** GNSS fix quality */
120 enum gnss_fix_quality {
121 /** Invalid fix */
122 GNSS_FIX_QUALITY_INVALID = 0,
123 /** Standard positioning service */
124 GNSS_FIX_QUALITY_GNSS_SPS = 1,
125 /** Differential GNSS */
126 GNSS_FIX_QUALITY_DGNSS = 2,
127 /** Precise positioning service */
128 GNSS_FIX_QUALITY_GNSS_PPS = 3,
129 /** Real-time kinematic */
130 GNSS_FIX_QUALITY_RTK = 4,
131 /** Floating real-time kinematic */
132 GNSS_FIX_QUALITY_FLOAT_RTK = 5,
133 /** Estimated fix */
134 GNSS_FIX_QUALITY_ESTIMATED = 6,
135 };
136
137 /** GNSS info data structure */
138 struct gnss_info {
139 /** Number of satellites being tracked */
140 uint16_t satellites_cnt;
141 /** Horizontal dilution of precision in 1/1000 */
142 uint32_t hdop;
143 /** The fix status */
144 enum gnss_fix_status fix_status;
145 /** The fix quality */
146 enum gnss_fix_quality fix_quality;
147 };
148
149 /** GNSS time data structure */
150 struct gnss_time {
151 /** Hour [0, 23] */
152 uint8_t hour;
153 /** Minute [0, 59] */
154 uint8_t minute;
155 /** Millisecond [0, 60999] */
156 uint16_t millisecond;
157 /** Day of month [1, 31] */
158 uint8_t month_day;
159 /** Month [1, 12] */
160 uint8_t month;
161 /** Year [0, 99] */
162 uint8_t century_year;
163 };
164
165 /** GNSS API structure */
166 __subsystem struct gnss_driver_api {
167 gnss_set_fix_rate_t set_fix_rate;
168 gnss_get_fix_rate_t get_fix_rate;
169 gnss_set_navigation_mode_t set_navigation_mode;
170 gnss_get_navigation_mode_t get_navigation_mode;
171 gnss_set_enabled_systems_t set_enabled_systems;
172 gnss_get_enabled_systems_t get_enabled_systems;
173 gnss_get_supported_systems_t get_supported_systems;
174 gnss_get_latest_timepulse_t get_latest_timepulse;
175 };
176
177 /** GNSS data structure */
178 struct gnss_data {
179 /** Navigation data acquired */
180 struct navigation_data nav_data;
181 /** GNSS info when navigation data was acquired */
182 struct gnss_info info;
183 /** UTC time when data was acquired */
184 struct gnss_time utc;
185 };
186
187 /** Template for GNSS data callback */
188 typedef void (*gnss_data_callback_t)(const struct device *dev, const struct gnss_data *data);
189
190 /** GNSS callback structure */
191 struct gnss_data_callback {
192 /** Filter callback to GNSS data from this device if not NULL */
193 const struct device *dev;
194 /** Callback called when GNSS data is published */
195 gnss_data_callback_t callback;
196 };
197
198 /** GNSS satellite structure */
199 struct gnss_satellite {
200 /** Pseudo-random noise sequence */
201 uint8_t prn;
202 /** Signal-to-noise ratio in dB */
203 uint8_t snr;
204 /** Elevation in degrees [0, 90] */
205 uint8_t elevation;
206 /** Azimuth relative to True North in degrees [0, 359] */
207 uint16_t azimuth;
208 /** System of satellite */
209 enum gnss_system system;
210 /** True if satellite is being tracked */
211 uint8_t is_tracked : 1;
212 };
213
214 /** Template for GNSS satellites callback */
215 typedef void (*gnss_satellites_callback_t)(const struct device *dev,
216 const struct gnss_satellite *satellites,
217 uint16_t size);
218
219 /** GNSS callback structure */
220 struct gnss_satellites_callback {
221 /** Filter callback to GNSS data from this device if not NULL */
222 const struct device *dev;
223 /** Callback called when GNSS satellites is published */
224 gnss_satellites_callback_t callback;
225 };
226
227 /**
228 * @brief Set the GNSS fix rate
229 *
230 * @param dev Device instance
231 * @param fix_interval_ms Fix interval to set in milliseconds
232 *
233 * @return 0 if successful
234 * @return -errno negative errno code on failure
235 */
236 __syscall int gnss_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms);
237
z_impl_gnss_set_fix_rate(const struct device * dev,uint32_t fix_interval_ms)238 static inline int z_impl_gnss_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms)
239 {
240 const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api;
241
242 if (api->set_fix_rate == NULL) {
243 return -ENOSYS;
244 }
245
246 return api->set_fix_rate(dev, fix_interval_ms);
247 }
248
249 /**
250 * @brief Get the GNSS fix rate
251 *
252 * @param dev Device instance
253 * @param fix_interval_ms Destination for fix interval in milliseconds
254 *
255 * @return 0 if successful
256 * @return -errno negative errno code on failure
257 */
258 __syscall int gnss_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms);
259
z_impl_gnss_get_fix_rate(const struct device * dev,uint32_t * fix_interval_ms)260 static inline int z_impl_gnss_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms)
261 {
262 const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api;
263
264 if (api->get_fix_rate == NULL) {
265 return -ENOSYS;
266 }
267
268 return api->get_fix_rate(dev, fix_interval_ms);
269 }
270
271 /**
272 * @brief Set the GNSS navigation mode
273 *
274 * @param dev Device instance
275 * @param mode Navigation mode to set
276 *
277 * @return 0 if successful
278 * @return -errno negative errno code on failure
279 */
280 __syscall int gnss_set_navigation_mode(const struct device *dev,
281 enum gnss_navigation_mode mode);
282
z_impl_gnss_set_navigation_mode(const struct device * dev,enum gnss_navigation_mode mode)283 static inline int z_impl_gnss_set_navigation_mode(const struct device *dev,
284 enum gnss_navigation_mode mode)
285 {
286 const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api;
287
288 if (api->set_navigation_mode == NULL) {
289 return -ENOSYS;
290 }
291
292 return api->set_navigation_mode(dev, mode);
293 }
294
295 /**
296 * @brief Get the GNSS navigation mode
297 *
298 * @param dev Device instance
299 * @param mode Destination for navigation mode
300 *
301 * @return 0 if successful
302 * @return -errno negative errno code on failure
303 */
304 __syscall int gnss_get_navigation_mode(const struct device *dev,
305 enum gnss_navigation_mode *mode);
306
z_impl_gnss_get_navigation_mode(const struct device * dev,enum gnss_navigation_mode * mode)307 static inline int z_impl_gnss_get_navigation_mode(const struct device *dev,
308 enum gnss_navigation_mode *mode)
309 {
310 const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api;
311
312 if (api->get_navigation_mode == NULL) {
313 return -ENOSYS;
314 }
315
316 return api->get_navigation_mode(dev, mode);
317 }
318
319 /**
320 * @brief Set enabled GNSS systems
321 *
322 * @param dev Device instance
323 * @param systems Systems to enable
324 *
325 * @return 0 if successful
326 * @return -errno negative errno code on failure
327 */
328 __syscall int gnss_set_enabled_systems(const struct device *dev, gnss_systems_t systems);
329
z_impl_gnss_set_enabled_systems(const struct device * dev,gnss_systems_t systems)330 static inline int z_impl_gnss_set_enabled_systems(const struct device *dev,
331 gnss_systems_t systems)
332 {
333 const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api;
334
335 if (api->set_enabled_systems == NULL) {
336 return -ENOSYS;
337 }
338
339 return api->set_enabled_systems(dev, systems);
340 }
341
342 /**
343 * @brief Get enabled GNSS systems
344 *
345 * @param dev Device instance
346 * @param systems Destination for enabled systems
347 *
348 * @return 0 if successful
349 * @return -errno negative errno code on failure
350 */
351 __syscall int gnss_get_enabled_systems(const struct device *dev, gnss_systems_t *systems);
352
z_impl_gnss_get_enabled_systems(const struct device * dev,gnss_systems_t * systems)353 static inline int z_impl_gnss_get_enabled_systems(const struct device *dev,
354 gnss_systems_t *systems)
355 {
356 const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api;
357
358 if (api->get_enabled_systems == NULL) {
359 return -ENOSYS;
360 }
361
362 return api->get_enabled_systems(dev, systems);
363 }
364
365 /**
366 * @brief Get supported GNSS systems
367 *
368 * @param dev Device instance
369 * @param systems Destination for supported systems
370 *
371 * @return 0 if successful
372 * @return -errno negative errno code on failure
373 */
374 __syscall int gnss_get_supported_systems(const struct device *dev, gnss_systems_t *systems);
375
z_impl_gnss_get_supported_systems(const struct device * dev,gnss_systems_t * systems)376 static inline int z_impl_gnss_get_supported_systems(const struct device *dev,
377 gnss_systems_t *systems)
378 {
379 const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api;
380
381 if (api->get_supported_systems == NULL) {
382 return -ENOSYS;
383 }
384
385 return api->get_supported_systems(dev, systems);
386 }
387
388 /**
389 * @brief Get the timestamp of the latest PPS timepulse
390 *
391 * @note The timestamp is considered valid when the timepulse pin is actively toggling.
392 *
393 * @param dev Device instance
394 * @param timestamp Kernel tick count at the time of the PPS pulse
395 *
396 * @retval 0 if successful
397 * @retval -ENOSYS if driver does not support API
398 * @retval -ENOTSUP if driver does not have PPS pin connected
399 * @retval -EAGAIN if PPS pulse is not considered valid
400 */
401 __syscall int gnss_get_latest_timepulse(const struct device *dev, k_ticks_t *timestamp);
402
z_impl_gnss_get_latest_timepulse(const struct device * dev,k_ticks_t * timestamp)403 static inline int z_impl_gnss_get_latest_timepulse(const struct device *dev,
404 k_ticks_t *timestamp)
405 {
406 const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api;
407
408 if (api->get_latest_timepulse == NULL) {
409 return -ENOSYS;
410 }
411
412 return api->get_latest_timepulse(dev, timestamp);
413 }
414
415 /**
416 * @brief Register a callback structure for GNSS data published
417 *
418 * @param _dev Device pointer
419 * @param _callback The callback function
420 */
421 #if CONFIG_GNSS
422 #define GNSS_DATA_CALLBACK_DEFINE(_dev, _callback) \
423 static const STRUCT_SECTION_ITERABLE(gnss_data_callback, \
424 _gnss_data_callback__##_callback) = { \
425 .dev = _dev, \
426 .callback = _callback, \
427 }
428 #else
429 #define GNSS_DATA_CALLBACK_DEFINE(_dev, _callback)
430 #endif
431
432 /**
433 * @brief Register a callback structure for GNSS satellites published
434 *
435 * @param _dev Device pointer
436 * @param _callback The callback function
437 */
438 #if CONFIG_GNSS_SATELLITES
439 #define GNSS_SATELLITES_CALLBACK_DEFINE(_dev, _callback) \
440 static const STRUCT_SECTION_ITERABLE(gnss_satellites_callback, \
441 _gnss_satellites_callback__##_callback) = { \
442 .dev = _dev, \
443 .callback = _callback, \
444 }
445 #else
446 #define GNSS_SATELLITES_CALLBACK_DEFINE(_dev, _callback)
447 #endif
448
449 /**
450 * @}
451 */
452
453 #ifdef __cplusplus
454 }
455 #endif
456
457 #include <zephyr/syscalls/gnss.h>
458
459 #endif /* ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ */
460