2 * This file is part of nmealib.
4 * Copyright (c) 2008 Timur Sinitsyn
5 * Copyright (c) 2011 Ferry Huberts
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <nmea/generate.h>
24 #include <nmea/conversions.h>
30 * Generate a GPGGA sentence from an nmeaGPGGA structure
32 * @param s a pointer to the buffer to generate the string in
33 * @param len the size of the buffer
34 * @param pack the structure
35 * @return the length of the generated sentence
37 int nmea_gen_GPGGA(char *s, const int len, const nmeaGPGGA *pack) {
58 sElvUnit[0] = sElvUnit[1] = 0;
60 if (nmea_INFO_is_present(pack->present, UTCTIME)) {
61 snprintf(&sTime[0], sizeof(sTime), "%02d%02d%02d.%02d", pack->utc.hour, pack->utc.min, pack->utc.sec,
64 if (nmea_INFO_is_present(pack->present, LAT)) {
65 snprintf(&sLat[0], sizeof(sLat), "%09.4f", pack->lat);
68 if (nmea_INFO_is_present(pack->present, LON)) {
69 snprintf(&sLon[0], sizeof(sLon), "%010.4f", pack->lon);
72 if (nmea_INFO_is_present(pack->present, SIG)) {
73 snprintf(&sSig[0], sizeof(sSig), "%1d", pack->sig);
75 if (nmea_INFO_is_present(pack->present, SATINUSECOUNT)) {
76 snprintf(&sSatInUse[0], sizeof(sSatInUse), "%02d", pack->satinuse);
78 if (nmea_INFO_is_present(pack->present, HDOP)) {
79 snprintf(&sHdop[0], sizeof(sHdop), "%03.1f", pack->HDOP);
81 if (nmea_INFO_is_present(pack->present, ELV)) {
82 snprintf(&sElv[0], sizeof(sElv), "%03.1f", pack->elv);
83 sElvUnit[0] = pack->elv_units;
86 return nmea_printf(s, len, "$GPGGA,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,,,,", &sTime[0], &sLat[0], &sNs[0],
87 &sLon[0], &sEw[0], &sSig[0], &sSatInUse[0], &sHdop[0], &sElv[0], &sElvUnit[0]);
91 * Generate a GPGSA sentence from an nmeaGPGSA structure
93 * @param s a pointer to the buffer to generate the string in
94 * @param len the size of the buffer
95 * @param pack the structure
96 * @return the length of the generated sentence
98 int nmea_gen_GPGSA(char *s, const int len, const nmeaGPGSA *pack) {
107 char * psSatPrn = &sSatPrn[0];
108 int ssSatPrn = sizeof(sSatPrn);
110 bool satinuse = nmea_INFO_is_present(pack->present, SATINUSE);
112 sFixMode[0] = sFixMode[1] = 0;
113 sFixType[0] = sFixType[1] = 0;
119 if (nmea_INFO_is_present(pack->present, FIX)) {
120 sFixMode[0] = pack->fix_mode;
121 snprintf(&sFixType[0], sizeof(sFixType), "%1d", pack->fix_type);
124 for (i = 0; i < NMEA_MAXSAT; i++) {
125 if (satinuse && pack->sat_prn[i]) {
126 int cnt = snprintf(psSatPrn, ssSatPrn, "%d", pack->sat_prn[i]);
127 if (cnt >= ssSatPrn) {
129 psSatPrn = &sSatPrn[sizeof(sSatPrn) - 1];
137 if (i < (NMEA_MAXSAT - 1)) {
145 if (nmea_INFO_is_present(pack->present, PDOP)) {
146 snprintf(&sPdop[0], sizeof(sPdop), "%03.1f", pack->PDOP);
148 if (nmea_INFO_is_present(pack->present, HDOP)) {
149 snprintf(&sHdop[0], sizeof(sHdop), "%03.1f", pack->HDOP);
151 if (nmea_INFO_is_present(pack->present, VDOP)) {
152 snprintf(&sVdop[0], sizeof(sVdop), "%03.1f", pack->VDOP);
155 return nmea_printf(s, len, "$GPGSA,%s,%s,%s,%s,%s,%s", &sFixMode[0], &sFixType[0], &sSatPrn[0], &sPdop[0],
156 &sHdop[0], &sVdop[0]);
160 * Generate a GPGSV sentence from an nmeaGPGSV structure
162 * @param s a pointer to the buffer to generate the string in
163 * @param len the size of the buffer
164 * @param pack the structure
165 * @return the length of the generated sentence
167 int nmea_gen_GPGSV(char *s, const int len, const nmeaGPGSV *pack) {
172 char * psSatInfo = &sSatInfo[0];
173 int ssSatInfo = sizeof(sSatInfo);
174 bool satinview = nmea_INFO_is_present(pack->present, SATINVIEW);
183 snprintf(&sCount[0], sizeof(sCount), "%1d", pack->pack_count);
184 snprintf(&sIndex[0], sizeof(sIndex), "%1d", pack->pack_index);
185 snprintf(&sSatCount[0], sizeof(sSatCount), "%02d", pack->sat_count);
187 for (i = 0; i < NMEA_SATINPACK; i++) {
189 if (satinview && pack->sat_data[i].id) {
190 cnt = snprintf(psSatInfo, ssSatInfo, "%02d,%02d,%03d,%02d", pack->sat_data[i].id, pack->sat_data[i].elv,
191 pack->sat_data[i].azimuth, pack->sat_data[i].sig);
193 cnt = snprintf(psSatInfo, ssSatInfo, ",,,");
195 if (cnt >= ssSatInfo) {
197 psSatInfo = &sSatInfo[sizeof(sSatInfo) - 1];
204 if (i < (NMEA_SATINPACK - 1)) {
212 return nmea_printf(s, len, "$GPGSV,%s,%s,%s,%s", &sCount[0], &sIndex[0], &sSatCount[0], &sSatInfo[0]);
216 * Generate a GPRMC sentence from an nmeaGPRMC structure
218 * @param s a pointer to the buffer to generate the string in
219 * @param len the size of the buffer
220 * @param pack the structure
221 * @return the length of the generated sentence
223 int nmea_gen_GPRMC(char *s, const int len, const nmeaGPRMC *pack) {
244 sMagvar_ew[0] = sMagvar_ew[1] = 0;
246 if (nmea_INFO_is_present(pack->present, UTCDATE)) {
247 snprintf(&sDate[0], sizeof(sDate), "%02d%02d%02d", pack->utc.day, pack->utc.mon + 1, pack->utc.year - 100);
249 if (nmea_INFO_is_present(pack->present, UTCTIME)) {
250 snprintf(&sTime[0], sizeof(sTime), "%02d%02d%02d.%02d", pack->utc.hour, pack->utc.min, pack->utc.sec,
253 if (nmea_INFO_is_present(pack->present, LAT)) {
254 snprintf(&sLat[0], sizeof(sLat), "%09.4f", pack->lat);
257 if (nmea_INFO_is_present(pack->present, LON)) {
258 snprintf(&sLon[0], sizeof(sLon), "%010.4f", pack->lon);
261 if (nmea_INFO_is_present(pack->present, SPEED)) {
262 snprintf(&sSpeed[0], sizeof(sSpeed), "%03.1f", pack->speed);
264 if (nmea_INFO_is_present(pack->present, TRACK)) {
265 snprintf(&sTrack[0], sizeof(sTrack), "%03.1f", pack->track);
267 if (nmea_INFO_is_present(pack->present, MAGVAR)) {
268 snprintf(&sMagvar[0], sizeof(sMagvar), "%03.1f", pack->magvar);
269 sMagvar_ew[0] = pack->magvar_ew;
272 return nmea_printf(s, len, "$GPRMC,%s,%C,%s,%s,%s,%s,%s,%s,%s,%s,%s,%C", &sTime[0], pack->status, &sLat[0], &sNs[0],
273 &sLon[0], &sEw[0], &sSpeed[0], &sTrack[0], &sDate[0], &sMagvar[0], &sMagvar_ew[0], pack->mode);
277 * Generate a GPVTG sentence from an nmeaGPVTG structure
279 * @param s a pointer to the buffer to generate the string in
280 * @param len the size of the buffer
281 * @param pack the structure
282 * @return the length of the generated sentence
284 int nmea_gen_GPVTG(char *s, const int len, const nmeaGPVTG *pack) {
298 sUnitT[0] = sUnitT[1] = 0;
299 sUnitM[0] = sUnitM[1] = 0;
300 sUnitN[0] = sUnitN[1] = 0;
301 sUnitK[0] = sUnitK[1] = 0;
303 if (nmea_INFO_is_present(pack->present, TRACK)) {
304 snprintf(&sTrackT[0], sizeof(sTrackT), "%03.1f", pack->track);
307 if (nmea_INFO_is_present(pack->present, MTRACK)) {
308 snprintf(&sTrackM[0], sizeof(sTrackM), "%03.1f", pack->mtrack);
311 if (nmea_INFO_is_present(pack->present, SPEED)) {
312 snprintf(&sSpeedN[0], sizeof(sSpeedN), "%03.1f", pack->spn);
314 snprintf(&sSpeedK[0], sizeof(sSpeedK), "%03.1f", pack->spk);
318 return nmea_printf(s, len, "$GPVTG,%s,%s,%s,%s,%s,%s,%s,%s", &sTrackT[0], &sUnitT[0], &sTrackM[0],
319 &sUnitM[0], &sSpeedN[0], &sUnitN[0], &sSpeedK[0], &sUnitK[0]);
323 * Generate a number of sentences from an nmeaINFO structure.
325 * @param s a pointer to the buffer in which to generate the sentences
326 * @param len the size of the buffer
327 * @param info the structure
328 * @param generate_mask the mask of which sentences to generate
329 * @return the total length of the generated sentences
331 int nmea_generate(char *s, const int len, const nmeaINFO *info, const int generate_mask) {
333 int pack_mask = generate_mask;
335 if (!s || !len || !info || !generate_mask)
339 if (pack_mask & GPGGA) {
342 nmea_info2GPGGA(info, &gga);
343 gen_count += nmea_gen_GPGGA(s + gen_count, len - gen_count, &gga);
345 } else if (pack_mask & GPGSA) {
348 nmea_info2GPGSA(info, &gsa);
349 gen_count += nmea_gen_GPGSA(s + gen_count, len - gen_count, &gsa);
351 } else if (pack_mask & GPGSV) {
354 int gsv_count = nmea_gsv_npack(info->satinfo.inview);
356 for (gsv_it = 0; gsv_it < gsv_count && len - gen_count > 0; gsv_it++) {
357 nmea_info2GPGSV(info, &gsv, gsv_it);
358 gen_count += nmea_gen_GPGSV(s + gen_count, len - gen_count, &gsv);
361 } else if (pack_mask & GPRMC) {
364 nmea_info2GPRMC(info, &rmc);
365 gen_count += nmea_gen_GPRMC(s + gen_count, len - gen_count, &rmc);
367 } else if (pack_mask & GPVTG) {
370 nmea_info2GPVTG(info, &vtg);
371 gen_count += nmea_gen_GPVTG(s + gen_count, len - gen_count, &vtg);
374 /* no more known sentences to process */
378 if (len - gen_count <= 0)