CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_Common/NMEA.cpp
Views: 1798
1
/*
2
This program is free software: you can redistribute it and/or modify
3
it under the terms of the GNU General Public License as published by
4
the Free Software Foundation, either version 3 of the License, or
5
(at your option) any later version.
6
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
11
12
You should have received a copy of the GNU General Public License
13
along with this program. If not, see <http://www.gnu.org/licenses/>.
14
*/
15
16
17
#include "NMEA.h"
18
19
extern const AP_HAL::HAL &hal;
20
21
/*
22
formatted print of NMEA message to an allocated string, with
23
checksum appended
24
*/
25
char *nmea_vaprintf(const char *fmt, va_list ap)
26
{
27
va_list ap_copy;
28
29
// we print once to nullptr to get the length
30
va_copy(ap_copy, ap);
31
int len = hal.util->vsnprintf(nullptr, 0, fmt, ap_copy);
32
va_end(ap_copy);
33
if (len <= 0) {
34
// can't print this format
35
return nullptr;
36
}
37
38
// now allocate the right length, including trailer
39
char *s = (char *)malloc(len+6);
40
if (s == nullptr) {
41
// allocation failed
42
return nullptr;
43
}
44
45
if (hal.util->vsnprintf(s, len+5, fmt, ap) < len) {
46
free(s);
47
// inconsistent formatting
48
return nullptr;
49
}
50
51
// calculate the checksum
52
uint8_t cs = 0;
53
const uint8_t *b = (const uint8_t *)s+1;
54
while (*b) {
55
cs ^= *b++;
56
}
57
58
hal.util->snprintf(s+len, 6, "*%02X\r\n", (unsigned)cs);
59
return s;
60
}
61
62
/*
63
formatted print of NMEA message to the port, with checksum appended
64
*/
65
bool nmea_printf(AP_HAL::UARTDriver *uart, const char *fmt, ...)
66
{
67
va_list ap;
68
69
va_start(ap, fmt);
70
char *s = nmea_vaprintf(fmt, ap);
71
va_end(ap);
72
if (s == nullptr) {
73
return false;
74
}
75
76
size_t len = strlen(s);
77
if (uart->txspace() < len) {
78
free(s);
79
return false;
80
}
81
uart->write((const uint8_t*)s, len);
82
free(s);
83
return true;
84
}
85
86
87
/*
88
formatted print of NMEA message to a buffer, with checksum appended.
89
Returns the length of the string filled into buf. If the NMEA string does not fit in the buffer, returns 0
90
*/
91
uint16_t nmea_printf_buffer(char* buf, const uint16_t buf_max_len, const char *fmt, ...)
92
{
93
va_list ap;
94
95
va_start(ap, fmt);
96
char *s = nmea_vaprintf(fmt, ap);
97
va_end(ap);
98
if (s == nullptr) {
99
return 0;
100
}
101
102
size_t len = strlen(s);
103
if (len > buf_max_len) {
104
// our string is larger than the buffer we've supplied.
105
// Instead of populating the buffer with a partial message, just quietly fail and do nothing
106
len = 0;
107
} else {
108
strncpy(buf, s, buf_max_len);
109
}
110
free(s);
111
112
return len;
113
}
114
115