STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
gnss_frame.c
Go to the documentation of this file.
1#include "gnss_frame.h"
2
3#include <string.h>
4
5enum {
6 IDLE = 0,
18};
19
20static int hex_value(uint8_t c) {
21 if (c >= '0' && c <= '9')
22 return c - '0';
23 if (c >= 'A' && c <= 'F')
24 return c - 'A' + 10;
25 if (c >= 'a' && c <= 'f')
26 return c - 'a' + 10;
27 return -1;
28}
29
30static void fletcher(gnss_frame_parser_t* p, uint8_t byte) {
31 p->ck_a = (uint8_t)(p->ck_a + byte);
32 p->ck_b = (uint8_t)(p->ck_b + p->ck_a);
33}
34
36 memset(parser, 0, sizeof(*parser));
37}
38
40 p->rejected++;
41 p->state = IDLE;
42}
43
44/* Begin a frame if this byte is a start marker; otherwise go idle. */
45static void start(gnss_frame_parser_t* p, uint8_t byte) {
46 if (byte == '$') {
47 p->state = NMEA_BODY;
48 p->xor_sum = 0;
49 p->count = 0;
50 } else if (byte == 0xB5) {
51 p->state = UBX_SYNC2;
52 } else {
53 p->state = IDLE;
54 }
55}
56
58 switch (p->state) {
59 case IDLE:
60 start(p, byte);
61 return GNSS_FRAME_NONE;
62
63 case NMEA_BODY:
64 if (byte == '*') {
65 p->state = NMEA_HEX_HI;
66 } else if (byte == '$') {
67 reject(p); /* a new sentence cut this one short */
68 start(p, byte);
69 } else if (byte < 0x20 || byte > 0x7E ||
70 ++p->count > GNSS_FRAME_NMEA_MAX_BODY) {
71 reject(p);
72 } else {
73 p->xor_sum ^= byte;
74 }
75 return GNSS_FRAME_NONE;
76
77 case NMEA_HEX_HI: {
78 int v = hex_value(byte);
79 if (v < 0) {
80 reject(p);
81 return GNSS_FRAME_NONE;
82 }
83 p->hex_hi = (uint8_t)v;
84 p->state = NMEA_HEX_LO;
85 return GNSS_FRAME_NONE;
86 }
87
88 case NMEA_HEX_LO: {
89 int v = hex_value(byte);
90 if (v < 0 || (uint8_t)((p->hex_hi << 4) | v) != p->xor_sum) {
91 reject(p);
92 return GNSS_FRAME_NONE;
93 }
94 p->state = IDLE;
95 return GNSS_FRAME_NMEA;
96 }
97
98 case UBX_SYNC2:
99 if (byte == 0x62) {
100 p->state = UBX_CLASS;
101 p->ck_a = p->ck_b = 0;
102 } else {
103 start(p, byte);
104 }
105 return GNSS_FRAME_NONE;
106
107 case UBX_CLASS:
108 fletcher(p, byte);
109 p->ubx_class = byte;
110 p->state = UBX_ID;
111 return GNSS_FRAME_NONE;
112
113 case UBX_ID:
114 fletcher(p, byte);
115 p->ubx_id = byte;
116 p->state = UBX_LEN_LO;
117 return GNSS_FRAME_NONE;
118
119 case UBX_LEN_LO:
120 fletcher(p, byte);
121 p->length = byte;
122 p->state = UBX_LEN_HI;
123 return GNSS_FRAME_NONE;
124
125 case UBX_LEN_HI:
126 fletcher(p, byte);
127 p->length = (uint16_t)(p->length | (uint16_t)(byte << 8));
128 if (p->length > GNSS_FRAME_UBX_MAX_PAYLOAD) {
129 reject(p);
130 return GNSS_FRAME_NONE;
131 }
132 p->count = 0;
133 p->ubx_len = p->length;
134 p->state = p->length ? UBX_PAYLOAD : UBX_CK_A;
135 return GNSS_FRAME_NONE;
136
137 case UBX_PAYLOAD:
138 fletcher(p, byte);
139 if (p->count < GNSS_FRAME_UBX_CAPTURE)
140 p->ubx_payload[p->count] = byte;
141 if (++p->count == p->length)
142 p->state = UBX_CK_A;
143 return GNSS_FRAME_NONE;
144
145 case UBX_CK_A:
146 if (byte != p->ck_a) {
147 reject(p);
148 return GNSS_FRAME_NONE;
149 }
150 p->state = UBX_CK_B;
151 return GNSS_FRAME_NONE;
152
153 case UBX_CK_B:
154 if (byte != p->ck_b) {
155 reject(p);
156 return GNSS_FRAME_NONE;
157 }
158 p->state = IDLE;
159 return GNSS_FRAME_UBX;
160
161 default:
162 p->state = IDLE;
163 return GNSS_FRAME_NONE;
164 }
165}
uint8_t byte
Minimal Arduino.h stub for native unit tests.
Definition Arduino.h:16
int32_t p
Definition flight_e2e.c:78
static void reject(gnss_frame_parser_t *p)
Definition gnss_frame.c:39
static void fletcher(gnss_frame_parser_t *p, uint8_t byte)
Definition gnss_frame.c:30
static int hex_value(uint8_t c)
Definition gnss_frame.c:20
@ NMEA_HEX_LO
Definition gnss_frame.c:9
@ NMEA_BODY
Definition gnss_frame.c:7
@ UBX_CK_B
Definition gnss_frame.c:17
@ UBX_CLASS
Definition gnss_frame.c:11
@ NMEA_HEX_HI
Definition gnss_frame.c:8
@ UBX_CK_A
Definition gnss_frame.c:16
@ UBX_SYNC2
Definition gnss_frame.c:10
@ UBX_LEN_LO
Definition gnss_frame.c:13
@ UBX_LEN_HI
Definition gnss_frame.c:14
@ UBX_ID
Definition gnss_frame.c:12
@ UBX_PAYLOAD
Definition gnss_frame.c:15
@ IDLE
Definition gnss_frame.c:6
gnss_frame_kind_t gnss_frame_feed(gnss_frame_parser_t *p, uint8_t byte)
Definition gnss_frame.c:57
static void start(gnss_frame_parser_t *p, uint8_t byte)
Definition gnss_frame.c:45
void gnss_frame_init(gnss_frame_parser_t *parser)
Definition gnss_frame.c:35
#define GNSS_FRAME_UBX_MAX_PAYLOAD
Definition gnss_frame.h:28
gnss_frame_kind_t
Definition gnss_frame.h:21
@ GNSS_FRAME_NONE
Definition gnss_frame.h:22
@ GNSS_FRAME_UBX
Definition gnss_frame.h:24
@ GNSS_FRAME_NMEA
Definition gnss_frame.h:23
#define GNSS_FRAME_NMEA_MAX_BODY
Definition gnss_frame.h:27
#define GNSS_FRAME_UBX_CAPTURE
Definition gnss_frame.h:30