1 /*
2  * Copyright (c) 2023 Trackunit Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_H_
8 #define ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_H_
9 
10 #include <zephyr/drivers/gnss.h>
11 
12 /**
13  * @brief Compute NMEA0183 checksum
14  *
15  * @example "PAIR002" -> 0x38
16  *
17  * @param str String from which checksum is computed
18  *
19  * @retval checksum
20  */
21 uint8_t gnss_nmea0183_checksum(const char *str);
22 
23 /**
24  * @brief Encapsulate str in NMEA0183 message format
25  *
26  * @example "PAIR%03u", 2 -> "$PAIR002*38"
27  *
28  * @param str Destination for encapsulated string
29  * @param size Size of destination for encapsulated string
30  * @param fmt Format of string to encapsulate
31  * @param ... Arguments
32  *
33  * @retval checksum
34  */
35 int gnss_nmea0183_snprintk(char *str, size_t size, const char *fmt, ...);
36 
37 /**
38  * @brief Computes and validates checksum
39  *
40  * @param argv Array of arguments split by ',' including message id and checksum
41  * @param argc Number of arguments in argv
42  *
43  * @retval true if message is intact
44  * @retval false if message is corrupted
45  */
46 bool gnss_nmea0183_validate_message(char **argv, uint16_t argc);
47 
48 /**
49  * @brief Parse a ddmm.mmmm formatted angle to nano degrees
50  *
51  * @example "5610.9928" -> 56183214000
52  *
53  * @param ddmm_mmmm String representation of angle in ddmm.mmmm format
54  * @param ndeg Result in nano degrees
55  *
56  * @retval -EINVAL if ddmm_mmmm argument is invalid
57  * @retval 0 if parsed successfully
58  */
59 int gnss_nmea0183_ddmm_mmmm_to_ndeg(const char *ddmm_mmmm, int64_t *ndeg);
60 
61 /**
62  * @brief Parse knots to millimeters pr second
63  *
64  * @example "15.231" -> 7835
65  *
66  * @param str String representation of speed in knots
67  * @param mms Destination for speed in millimeters pr second
68  *
69  * @retval -EINVAL if str could not be parsed or if speed is negative
70  * @retval 0 if parsed successfully
71  */
72 int gnss_nmea0183_knots_to_mms(const char *str, int64_t *mms);
73 
74 /**
75  * @brief Parse hhmmss.sss to struct gnss_time
76  *
77  * @example "133243.012" -> { .hour = 13, .minute = 32, .ms = 43012 }
78  * @example "133243" -> { .hour = 13, .minute = 32, .ms = 43000 }
79  *
80  * @param str String representation of hours, minutes, seconds and subseconds
81  * @param utc Destination for parsed time
82  *
83  * @retval -EINVAL if str could not be parsed
84  * @retval 0 if parsed successfully
85  */
86 int gnss_nmea0183_parse_hhmmss(const char *hhmmss, struct gnss_time *utc);
87 
88 /**
89  * @brief Parse ddmmyy to unsigned integers
90  *
91  * @example "041122" -> { .mday = 4, .month = 11, .year = 22 }
92  *
93  * @param str String representation of speed in knots
94  * @param utc Destination for parsed time
95  *
96  * @retval -EINVAL if str could not be parsed
97  * @retval 0 if parsed successfully
98  */
99 int gnss_nmea0183_parse_ddmmyy(const char *ddmmyy, struct gnss_time *utc);
100 
101 /**
102  * @brief Parses NMEA0183 RMC message
103  *
104  * @details Parses the time, date, latitude, longitude, speed, and bearing
105  * from the NMEA0183 RMC message provided as an array of strings split by ','
106  *
107  * @param argv Array of arguments split by ',' including message id and checksum
108  * @param argc Number of arguments in argv'
109  * @param data Destination for data parsed from NMEA0183 RMC message
110  *
111  * @retval 0 if successful
112  * @retval -EINVAL if input is invalid
113  */
114 int gnss_nmea0183_parse_rmc(const char **argv, uint16_t argc, struct gnss_data *data);
115 
116 /**
117  * @brief Parses NMEA0183 GGA message
118  *
119  * @details Parses the GNSS fix quality and status, number of satellites used for
120  * fix, HDOP, and altitude (geoid separation) from the NMEA0183 GGA message provided
121  * as an array of strings split by ','
122  *
123  * @param argv Array of arguments split by ',' including message id and checksum
124  * @param argc Number of arguments in argv'
125  * @param data Destination for data parsed from NMEA0183 GGA message
126  *
127  * @retval 0 if successful
128  * @retval -EINVAL if input is invalid
129  */
130 int gnss_nmea0183_parse_gga(const char **argv, uint16_t argc, struct gnss_data *data);
131 
132 /** GSV header structure */
133 struct gnss_nmea0183_gsv_header {
134 	/** Indicates the system of the space-vehicles contained in the message */
135 	enum gnss_system system;
136 	/** Number of GSV messages in total */
137 	uint16_t number_of_messages;
138 	/** Number of this GSV message */
139 	uint16_t message_number;
140 	/** Number of visible space-vehicles */
141 	uint16_t number_of_svs;
142 };
143 
144 /**
145  * @brief Parses header of NMEA0183 GSV message
146  *
147  * @details The GSV messages are part of a list of messages sent in ascending
148  * order, split by GNSS system.
149  *
150  * @param argv Array of arguments split by ',' including message id and checksum
151  * @param argc Number of arguments in argv
152  * @param header Destination for parsed NMEA0183 GGA message header
153  *
154  * @retval 0 if successful
155  * @retval -EINVAL if input is invalid
156  */
157 int gnss_nmea0183_parse_gsv_header(const char **argv, uint16_t argc,
158 				   struct gnss_nmea0183_gsv_header *header);
159 
160 /**
161  * @brief Parses space-vehicles in NMEA0183 GSV message
162  *
163  * @details The NMEA0183 GSV message contains up to 4 space-vehicles which follow
164  * the header.
165  *
166  * @param argv Array of arguments split by ',' including message id and checksum
167  * @param argc Number of arguments in argv
168  * @param satellites Destination for parsed satellites from NMEA0183 GGA message
169  * @param size Size of destination for parsed satellites from NMEA0183 GGA message
170  *
171  * @retval Number of parsed space-vehicles stored at destination if successful
172  * @retval -ENOMEM if all space-vehicles in message could not be stored at destination
173  * @retval -EINVAL if input is invalid
174  */
175 int gnss_nmea0183_parse_gsv_svs(const char **argv, uint16_t argc,
176 				struct gnss_satellite *satellites, uint16_t size);
177 
178 #endif /* ZEPHYR_DRIVERS_GNSS_GNSS_NMEA0183_H_ */
179