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