11#if DETWS_ENABLE_NMEA0183
16uint8_t nmea0183_checksum(
const char *s,
size_t len)
19 for (
size_t i = 0; i < len; i++)
24static char hex_digit(uint8_t v)
27 return (
char)(v < 10 ? (
'0' + v) : (
'A' + v - 10));
30static int hex_val(
char c)
32 if (c >=
'0' && c <=
'9')
34 if (c >=
'A' && c <=
'F')
36 if (c >=
'a' && c <=
'f')
41size_t nmea0183_build(
char *buf,
size_t cap,
const char *body)
45 size_t blen = strnlen(body, cap);
46 size_t total = 1 + blen + 1 + 2 + 2;
49 uint8_t cs = nmea0183_checksum(body, blen);
52 memcpy(buf + p, body, blen);
55 buf[p++] = hex_digit((uint8_t)(cs >> 4));
56 buf[p++] = hex_digit(cs);
63bool nmea0183_parse(
const char *s,
size_t len, Nmea0183 *out)
65 if (!s || !out || len < 4 || (s[0] !=
'$' && s[0] !=
'!'))
71 for (
size_t i = 1; i < len; i++)
79 if (s[i] ==
'\r' || s[i] ==
'\n')
82 if (!found || star + 2 >= len)
85 int hi = hex_val(s[star + 1]);
86 int lo = hex_val(s[star + 2]);
89 uint8_t expect = (uint8_t)((hi << 4) | lo);
90 if (nmea0183_checksum(s + 1, star - 1) != expect)
96 for (
size_t i = 1; i <= star; i++)
98 if (i == star || s[i] ==
',')
100 if (fc < DETWS_NMEA0183_MAX_FIELDS)
102 out->fields[fc] = s + fstart;
103 out->field_len[fc] = (uint8_t)(i - fstart);
109 out->field_count = fc;
112 memset(out->talker, 0,
sizeof(out->talker));
113 memset(out->type, 0,
sizeof(out->type));
116 uint8_t al = out->field_len[0];
117 const char *a = out->fields[0];
118 for (uint8_t i = 0; i < 2 && i < al; i++)
119 out->talker[i] = a[i];
120 for (uint8_t i = 0; i < 3 && (uint8_t)(2 + i) < al; i++)
121 out->type[i] = a[2 + i];
126bool nmea0183_field_float(
const Nmea0183 *m, uint8_t idx,
float *out)
128 if (!m || !out || idx >= m->field_count || m->field_len[idx] == 0)
130 const char *end = m->fields[idx];
133 if (end == m->fields[idx])
139bool nmea0183_field_int(
const Nmea0183 *m, uint8_t idx,
long *out)
141 if (!m || !out || idx >= m->field_count || m->field_len[idx] == 0)
143 const char *end = m->fields[idx];
145 if (end == m->fields[idx])
NMEA 0183 sentence codec (DETWS_ENABLE_NMEA0183) - the marine / GPS ASCII protocol.
Tiny no-stdlib base-10 number parsers (strtol/strtoul/strtof replacements).
float det_strtof(const char *s, const char **end)
Parse a float (integer[.frac][e[+/-]exp]); sets end (or to s if none).
long det_strtol(const char *s, const char **end)
Parse a base-10 long; sets end past the digits (or to s if none).