QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
UBXFrame.h
Go to the documentation of this file.
1// Message classes and ids, and the frame layout, as the u-blox interface descriptions define them.
2#pragma once
3
4#include <algorithm>
5#include <array>
6#include <cstddef>
7#include <cstdint>
8#include <optional>
9#include <span>
10#include <string_view>
11#include <utility>
12
13#include <QtCore/QByteArray>
14#include <QtCore/QByteArrayView>
15
16#include "Checksums.h"
17
18namespace UBX {
19
23{
24 uint8_t cls;
25 uint8_t id;
26
27 [[nodiscard]] constexpr uint16_t value() const { return static_cast<uint16_t>(cls | (id << 8)); }
28};
29
30} // namespace UBX
31
32namespace UBX::MsgClass {
33inline constexpr uint8_t NAV = 0x01;
34inline constexpr uint8_t RXM = 0x02;
35inline constexpr uint8_t INF = 0x04;
36inline constexpr uint8_t ACK = 0x05;
37inline constexpr uint8_t CFG = 0x06;
38inline constexpr uint8_t MON = 0x0a;
39inline constexpr uint8_t SEC = 0x27;
40inline constexpr uint8_t RTCM3 = 0xf5;
41} // namespace UBX::MsgClass
42
43namespace UBX::Msg {
44inline constexpr MessageId NAV_STATUS{MsgClass::NAV, 0x03};
45inline constexpr MessageId NAV_DOP{MsgClass::NAV, 0x04};
46inline constexpr MessageId NAV_PVT{MsgClass::NAV, 0x07};
47inline constexpr MessageId NAV_HPPOSLLH{MsgClass::NAV, 0x14};
48inline constexpr MessageId NAV_TIMEGPS{MsgClass::NAV, 0x20};
49inline constexpr MessageId NAV_SVINFO{MsgClass::NAV, 0x30};
50inline constexpr MessageId NAV_SAT{MsgClass::NAV, 0x35};
51inline constexpr MessageId NAV_SVIN{MsgClass::NAV, 0x3b};
52inline constexpr MessageId NAV_EOE{MsgClass::NAV, 0x61};
53inline constexpr MessageId RXM_SFRBX{MsgClass::RXM, 0x13};
54inline constexpr MessageId RXM_RAWX{MsgClass::RXM, 0x15};
55inline constexpr MessageId INF_ERROR{MsgClass::INF, 0x00};
56inline constexpr MessageId INF_WARNING{MsgClass::INF, 0x01};
57inline constexpr MessageId INF_NOTICE{MsgClass::INF, 0x02};
58inline constexpr MessageId INF_DEBUG{MsgClass::INF, 0x04};
59inline constexpr MessageId ACK_NAK{MsgClass::ACK, 0x00};
60inline constexpr MessageId ACK_ACK{MsgClass::ACK, 0x01};
61inline constexpr MessageId CFG_PRT{MsgClass::CFG, 0x00};
62inline constexpr MessageId CFG_MSG{MsgClass::CFG, 0x01};
63inline constexpr MessageId CFG_RATE{MsgClass::CFG, 0x08};
64inline constexpr MessageId CFG_NAV5{MsgClass::CFG, 0x24};
65inline constexpr MessageId CFG_TMODE3{MsgClass::CFG, 0x71};
66inline constexpr MessageId CFG_VALSET{MsgClass::CFG, 0x8a};
67inline constexpr MessageId CFG_VALGET{MsgClass::CFG, 0x8b};
68inline constexpr MessageId MON_VER{MsgClass::MON, 0x04};
69inline constexpr MessageId MON_HW{MsgClass::MON, 0x09};
70inline constexpr MessageId MON_RF{MsgClass::MON, 0x38};
71inline constexpr MessageId SEC_SIG{MsgClass::SEC, 0x09};
72inline constexpr MessageId RTCM3_1005{MsgClass::RTCM3, 0x05};
73inline constexpr MessageId RTCM3_1074{MsgClass::RTCM3, 0x4a};
74inline constexpr MessageId RTCM3_1077{MsgClass::RTCM3, 0x4d};
75inline constexpr MessageId RTCM3_1084{MsgClass::RTCM3, 0x54};
76inline constexpr MessageId RTCM3_1087{MsgClass::RTCM3, 0x57};
77inline constexpr MessageId RTCM3_1094{MsgClass::RTCM3, 0x5e};
78inline constexpr MessageId RTCM3_1097{MsgClass::RTCM3, 0x61};
79inline constexpr MessageId RTCM3_1124{MsgClass::RTCM3, 0x7c};
80inline constexpr MessageId RTCM3_1127{MsgClass::RTCM3, 0x7f};
81inline constexpr MessageId RTCM3_1230{MsgClass::RTCM3, 0xe6};
82} // namespace UBX::Msg
83
84namespace UBX {
85
87inline constexpr std::pair<MessageId, std::string_view> MESSAGE_NAMES[] = {
88 {Msg::NAV_STATUS, "UBX-NAV-STATUS"}, {Msg::NAV_DOP, "UBX-NAV-DOP"}, {Msg::NAV_PVT, "UBX-NAV-PVT"},
89 {Msg::NAV_HPPOSLLH, "UBX-NAV-HPPOSLLH"}, {Msg::NAV_TIMEGPS, "UBX-NAV-TIMEGPS"}, {Msg::NAV_SVINFO, "UBX-NAV-SVINFO"},
90 {Msg::NAV_SAT, "UBX-NAV-SAT"}, {Msg::NAV_SVIN, "UBX-NAV-SVIN"}, {Msg::NAV_EOE, "UBX-NAV-EOE"},
91 {Msg::RXM_SFRBX, "UBX-RXM-SFRBX"}, {Msg::RXM_RAWX, "UBX-RXM-RAWX"}, {Msg::INF_ERROR, "UBX-INF-ERROR"},
92 {Msg::INF_WARNING, "UBX-INF-WARNING"}, {Msg::INF_NOTICE, "UBX-INF-NOTICE"}, {Msg::INF_DEBUG, "UBX-INF-DEBUG"},
93 {Msg::ACK_NAK, "UBX-ACK-NAK"}, {Msg::ACK_ACK, "UBX-ACK-ACK"}, {Msg::CFG_PRT, "UBX-CFG-PRT"},
94 {Msg::CFG_MSG, "UBX-CFG-MSG"}, {Msg::CFG_RATE, "UBX-CFG-RATE"}, {Msg::CFG_NAV5, "UBX-CFG-NAV5"},
95 {Msg::CFG_TMODE3, "UBX-CFG-TMODE3"}, {Msg::CFG_VALSET, "UBX-CFG-VALSET"}, {Msg::CFG_VALGET, "UBX-CFG-VALGET"},
96 {Msg::MON_VER, "UBX-MON-VER"}, {Msg::MON_HW, "UBX-MON-HW"}, {Msg::MON_RF, "UBX-MON-RF"},
97 {Msg::SEC_SIG, "UBX-SEC-SIG"}, {Msg::RTCM3_1005, "RTCM3-1005"}, {Msg::RTCM3_1074, "RTCM3-1074"},
98 {Msg::RTCM3_1077, "RTCM3-1077"}, {Msg::RTCM3_1084, "RTCM3-1084"}, {Msg::RTCM3_1087, "RTCM3-1087"},
99 {Msg::RTCM3_1094, "RTCM3-1094"}, {Msg::RTCM3_1097, "RTCM3-1097"}, {Msg::RTCM3_1124, "RTCM3-1124"},
100 {Msg::RTCM3_1127, "RTCM3-1127"}, {Msg::RTCM3_1230, "RTCM3-1230"},
101};
102
104[[nodiscard]] inline QByteArray messageName(MessageId message)
105{
106 for (const auto& [id, name] : MESSAGE_NAMES) {
107 if (id.value() == message.value()) {
108 return QByteArrayView(name).toByteArray();
109 }
110 }
111 return QByteArrayLiteral("UBX-0x") + QByteArray::number(message.cls, 16) + "-0x" +
112 QByteArray::number(message.id, 16);
113}
114
115} // namespace UBX
116
117namespace UBX {
118inline constexpr uint8_t SYNC1 = 0xb5;
119inline constexpr uint8_t SYNC2 = 0x62;
120inline constexpr size_t HEADER_SIZE = 6;
122inline constexpr size_t FRAME_OVERHEAD = HEADER_SIZE + 2;
124inline constexpr size_t MAX_PAYLOAD_SIZE = 4096;
127inline constexpr size_t MAX_SKIPPED_PAYLOAD_SIZE = 8192;
128
130[[nodiscard]] constexpr std::span<const uint8_t> encodeFrame(MessageId message, std::span<const uint8_t> payload,
131 std::span<uint8_t> out)
132{
133 const size_t size = payload.size() + FRAME_OVERHEAD;
134 if (payload.size() > MAX_PAYLOAD_SIZE || size > out.size()) {
135 return {};
136 }
137 out[0] = SYNC1;
138 out[1] = SYNC2;
139 out[2] = message.cls;
140 out[3] = message.id;
141 out[4] = static_cast<uint8_t>(payload.size());
142 out[5] = static_cast<uint8_t>(payload.size() >> 8);
143 std::copy(payload.begin(), payload.end(), out.begin() + HEADER_SIZE);
144 const auto checksum = QGC::fletcher8(out.subspan(2, size - 4));
145 out[size - 2] = checksum.a;
146 out[size - 1] = checksum.b;
147 return out.first(size);
148}
149
151struct Frame
152{
153 uint16_t message = 0;
155 std::span<const uint8_t> bytes;
156 std::span<const uint8_t> payload;
157};
158
160{
161public:
162 [[nodiscard]] bool idle() const { return _state == State::Sync1; }
163
164 void reset()
165 {
166 _state = State::Sync1;
167 _checksum = {};
168 }
169
170 [[nodiscard]] std::optional<Frame> consume(uint8_t byte)
171 {
172 switch (_state) {
173 case State::Sync1:
174 if (byte == SYNC1) {
175 _state = State::Sync2;
176 }
177 break;
178 case State::Sync2:
179 if (byte == SYNC2) {
180 _size = 2;
181 _state = State::Header;
182 } else if (byte != SYNC1) {
183 reset();
184 }
185 break;
186 case State::Header:
187 _add(byte);
188 if (_size == HEADER_SIZE) {
189 _length = static_cast<uint16_t>(_bytes[4] | (_bytes[5] << 8));
190 _payloadRead = 0;
191 if (_length > MAX_SKIPPED_PAYLOAD_SIZE) {
192 reset();
193 } else {
194 _state = _length ? State::Payload : State::Checksum1;
195 }
196 }
197 break;
198 case State::Payload:
199 if (_length <= MAX_PAYLOAD_SIZE) {
200 _add(byte);
201 } else {
202 _checksum = QGC::fletcher8({&byte, 1}, _checksum);
203 }
204 if (++_payloadRead == _length) {
205 _state = State::Checksum1;
206 }
207 break;
208 case State::Checksum1:
209 if (byte == _checksum.a) {
210 _bytes[_size++] = byte;
211 _state = State::Checksum2;
212 } else {
213 reset();
214 }
215 break;
216 case State::Checksum2: {
217 const bool valid = byte == _checksum.b && _length <= MAX_PAYLOAD_SIZE;
218 reset();
219 if (valid) {
220 _bytes[_size++] = byte;
221 const std::span<const uint8_t> bytes(_bytes.data(), _size);
222 return Frame{static_cast<uint16_t>(_bytes[2] | (_bytes[3] << 8)), bytes,
223 bytes.subspan(HEADER_SIZE, _length)};
224 }
225 break;
226 }
227 }
228 return std::nullopt;
229 }
230
231private:
232 enum class State
233 {
234 Sync1,
235 Sync2,
236 Header,
237 Payload,
238 Checksum1,
239 Checksum2
240 };
241
242 void _add(uint8_t byte)
243 {
244 _checksum = QGC::fletcher8({&byte, 1}, _checksum);
245 _bytes[_size++] = byte;
246 }
247
248 std::array<uint8_t, MAX_PAYLOAD_SIZE + FRAME_OVERHEAD> _bytes{SYNC1, SYNC2};
249 size_t _size = 0;
250 uint16_t _length = 0;
251 uint16_t _payloadRead = 0;
252 State _state = State::Sync1;
253 QGC::Fletcher8 _checksum;
254};
255} // namespace UBX
bool idle() const
Definition UBXFrame.h:162
std::optional< Frame > consume(uint8_t byte)
Definition UBXFrame.h:170
constexpr Fletcher8 fletcher8(std::span< const uint8_t > bytes, Fletcher8 state={})
Continues state over bytes, so a frame checksummed in parts matches the contiguous result.
Definition Checksums.h:18
constexpr uint8_t RXM
Definition UBXFrame.h:34
constexpr uint8_t NAV
Definition UBXFrame.h:33
constexpr uint8_t INF
Definition UBXFrame.h:35
constexpr uint8_t SEC
Definition UBXFrame.h:39
constexpr uint8_t MON
Definition UBXFrame.h:38
constexpr uint8_t RTCM3
Definition UBXFrame.h:40
constexpr uint8_t ACK
Definition UBXFrame.h:36
constexpr uint8_t CFG
Definition UBXFrame.h:37
constexpr MessageId CFG_VALSET
Definition UBXFrame.h:66
constexpr MessageId NAV_SVIN
Definition UBXFrame.h:51
constexpr MessageId ACK_NAK
Definition UBXFrame.h:59
constexpr MessageId RTCM3_1074
Definition UBXFrame.h:73
constexpr MessageId MON_HW
Definition UBXFrame.h:69
constexpr MessageId INF_DEBUG
Definition UBXFrame.h:58
constexpr MessageId MON_RF
Definition UBXFrame.h:70
constexpr MessageId SEC_SIG
Definition UBXFrame.h:71
constexpr MessageId RTCM3_1124
Definition UBXFrame.h:79
constexpr MessageId NAV_EOE
Definition UBXFrame.h:52
constexpr MessageId RTCM3_1077
Definition UBXFrame.h:74
constexpr MessageId ACK_ACK
Definition UBXFrame.h:60
constexpr MessageId RTCM3_1127
Definition UBXFrame.h:80
constexpr MessageId NAV_STATUS
Definition UBXFrame.h:44
constexpr MessageId NAV_DOP
Definition UBXFrame.h:45
constexpr MessageId RTCM3_1097
Definition UBXFrame.h:78
constexpr MessageId RXM_SFRBX
Definition UBXFrame.h:53
constexpr MessageId RTCM3_1230
Definition UBXFrame.h:81
constexpr MessageId NAV_TIMEGPS
Definition UBXFrame.h:48
constexpr MessageId CFG_VALGET
Definition UBXFrame.h:67
constexpr MessageId CFG_RATE
Definition UBXFrame.h:63
constexpr MessageId RXM_RAWX
Definition UBXFrame.h:54
constexpr MessageId NAV_SAT
Definition UBXFrame.h:50
constexpr MessageId MON_VER
Definition UBXFrame.h:68
constexpr MessageId RTCM3_1087
Definition UBXFrame.h:76
constexpr MessageId NAV_SVINFO
Definition UBXFrame.h:49
constexpr MessageId RTCM3_1005
Definition UBXFrame.h:72
constexpr MessageId INF_WARNING
Definition UBXFrame.h:56
constexpr MessageId CFG_MSG
Definition UBXFrame.h:62
constexpr MessageId CFG_NAV5
Definition UBXFrame.h:64
constexpr MessageId INF_ERROR
Definition UBXFrame.h:55
constexpr MessageId CFG_TMODE3
Definition UBXFrame.h:65
constexpr MessageId INF_NOTICE
Definition UBXFrame.h:57
constexpr MessageId NAV_HPPOSLLH
Definition UBXFrame.h:47
constexpr MessageId RTCM3_1084
Definition UBXFrame.h:75
constexpr MessageId NAV_PVT
Definition UBXFrame.h:46
constexpr MessageId RTCM3_1094
Definition UBXFrame.h:77
constexpr MessageId CFG_PRT
Definition UBXFrame.h:61
u-blox receivers over UBX: CFG-VALSET configuration from protocol 27, CFG-MSG and CFG-TMODE3 before i...
constexpr uint8_t SYNC2
Definition UBXFrame.h:119
constexpr size_t HEADER_SIZE
Definition UBXFrame.h:120
constexpr std::pair< MessageId, std::string_view > MESSAGE_NAMES[]
Readable names of the messages above, as the interface description writes them.
Definition UBXFrame.h:87
constexpr size_t FRAME_OVERHEAD
Header and checksum.
Definition UBXFrame.h:122
constexpr std::span< const uint8_t > encodeFrame(MessageId message, std::span< const uint8_t > payload, std::span< uint8_t > out)
Writes the frame of payload to the front of out.
Definition UBXFrame.h:130
constexpr size_t MAX_SKIPPED_PAYLOAD_SIZE
Definition UBXFrame.h:127
constexpr size_t MAX_PAYLOAD_SIZE
The longest payload decoded.
Definition UBXFrame.h:124
QByteArray messageName(MessageId message)
The name of message, such as "UBX-CFG-VALSET", or its class and id in hex when it has none.
Definition UBXFrame.h:104
constexpr uint8_t SYNC1
Definition UBXFrame.h:118
8-bit Fletcher checksum: two running byte sums modulo 256.
Definition Checksums.h:10
A received frame. Its views borrow the decoder's storage until the next consume().
Definition UBXFrame.h:152
std::span< const uint8_t > bytes
From the sync bytes to the checksum.
Definition UBXFrame.h:155
uint16_t message
Definition UBXFrame.h:153
std::span< const uint8_t > payload
Definition UBXFrame.h:156
uint8_t cls
Definition UBXFrame.h:24
constexpr uint16_t value() const
Definition UBXFrame.h:27
uint8_t id
Definition UBXFrame.h:25