QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
RTCMFramer.h
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cstddef>
5#include <cstdint>
6#include <optional>
7#include <span>
8
9#include <QtCore/QByteArray>
10#include <QtCore/QByteArrayView>
11#include <QtCore/QSet>
12#include <QtCore/QVector>
13
14#include "Checksums.h"
15
19{
20public:
21 static constexpr uint8_t PREAMBLE = 0xd3;
22 static constexpr uint16_t HEADER_SIZE = 3;
23 static constexpr uint16_t CRC_SIZE = 3;
24 static constexpr uint16_t MAX_PAYLOAD_SIZE = 1023;
25 static constexpr uint16_t MAX_FRAME_SIZE = HEADER_SIZE + MAX_PAYLOAD_SIZE + CRC_SIZE;
26
27 void reset()
28 {
29 _size = 0;
30 _payloadSize = 0;
31 _frameSize = 0;
32 _recoverySize = 0;
33 _valid = false;
34 }
35
36 bool addByte(uint8_t byte);
37 bool nextFrame();
38
39 bool hasPartialFrame() const { return _size != 0 && !_frameSize; }
40
42 std::span<const uint8_t> frame() const { return {_bytes.data(), _frameSize}; }
43
45 uint16_t bufferedSize() const { return _size; }
46
47 uint16_t payloadLength() const { return _payloadSize; }
48
49 uint16_t messageId() const
50 {
51 const uint16_t available = _frameSize ? _frameSize : _size;
52 return payloadLength() >= 2 ? frameMessageId(std::span<const uint8_t>(_bytes.data(), available)) : 0;
53 }
54
56 [[nodiscard]] static uint16_t frameMessageId(std::span<const uint8_t> bytes)
57 {
58 return bytes.size() >= HEADER_SIZE + 2 && bytes[0] == PREAMBLE ? (bytes[3] << 4) | (bytes[4] >> 4) : 0;
59 }
60
61 bool valid() const { return _valid; }
62
63 [[nodiscard]] static bool isValidFrame(std::span<const uint8_t> bytes)
64 {
65 if (bytes.size() < HEADER_SIZE + 2 + CRC_SIZE || bytes[0] != PREAMBLE || (bytes[1] & 0xfc)) {
66 return false;
67 }
68 const size_t payloadSize = ((bytes[1] & 3) << 8) | bytes[2];
69 return bytes.size() == HEADER_SIZE + payloadSize + CRC_SIZE && QGC::crc24q(bytes) == 0;
70 }
71
72 [[nodiscard]] static bool isValidFrame(QByteArrayView bytes)
73 {
74 return isValidFrame(std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(bytes.data()),
75 static_cast<size_t>(bytes.size())));
76 }
77
78private:
79 void _discardPrefix(uint16_t count);
80 uint16_t _discardCandidate();
81 bool _inspect(uint16_t validatedFrameSize);
82
83 std::array<uint8_t, MAX_FRAME_SIZE> _bytes{};
84 uint16_t _size = 0;
85 uint16_t _payloadSize = 0;
86 uint16_t _frameSize = 0;
87 uint16_t _recoverySize = 0;
88 bool _valid = false;
89};
90
92{
93 QByteArray data;
94 int messageId = 0;
95 qint64 receivedAtMs = 0;
96 bool valid = false;
97 bool filtered = false;
98};
99
102{
103public:
106
107 std::optional<RTCMDecodedFrame> addByte(uint8_t byte, qint64 receivedAtMs);
109 std::optional<RTCMDecodedFrame> nextFrame();
110 void reset();
111
114 template <typename Deliver>
115 bool feed(QByteArrayView bytes, qint64 receivedAtMs, Deliver&& deliver)
116 {
117 for (const char byte : bytes) {
118 for (auto frame = addByte(static_cast<uint8_t>(byte), receivedAtMs); frame; frame = nextFrame()) {
119 if (!deliver(*frame)) {
120 return false;
121 }
122 }
123 }
124 return true;
125 }
126
127 void setWhitelist(const QVector<int>& ids) { _whitelist = QSet<int>(ids.begin(), ids.end()); }
128
129private:
130 RTCMDecodedFrame _result() const;
131
132 RTCMFramer _framer;
133 QSet<int> _whitelist;
134 std::array<qint64, RTCMFramer::MAX_FRAME_SIZE> _receiptTimes{};
135 size_t _nextReceiptIndex = 0;
136};
Frames RTCM bytes while retaining the first fragment's monotonic receipt time.
Definition RTCMFramer.h:102
void setWhitelist(const QVector< int > &ids)
Definition RTCMFramer.h:127
std::optional< RTCMDecodedFrame > nextFrame()
Drain after addByte() returns a result, before feeding more bytes.
bool feed(QByteArrayView bytes, qint64 receivedAtMs, Deliver &&deliver)
Definition RTCMFramer.h:115
std::optional< RTCMDecodedFrame > addByte(uint8_t byte, qint64 receivedAtMs)
static constexpr uint16_t CRC_SIZE
Definition RTCMFramer.h:23
uint16_t messageId() const
Definition RTCMFramer.h:49
std::span< const uint8_t > frame() const
Complete candidate, including malformed headers; empty while incomplete.
Definition RTCMFramer.h:42
bool nextFrame()
Definition RTCMFramer.cc:31
uint16_t bufferedSize() const
Retained suffix length, including bytes beyond the current candidate.
Definition RTCMFramer.h:45
uint16_t payloadLength() const
Definition RTCMFramer.h:47
void reset()
Definition RTCMFramer.h:27
static constexpr uint16_t HEADER_SIZE
Definition RTCMFramer.h:22
bool hasPartialFrame() const
Definition RTCMFramer.h:39
static constexpr uint8_t PREAMBLE
Definition RTCMFramer.h:21
static constexpr uint16_t MAX_PAYLOAD_SIZE
Definition RTCMFramer.h:24
static uint16_t frameMessageId(std::span< const uint8_t > bytes)
Message number from a frame header; zero when the header is incomplete.
Definition RTCMFramer.h:56
static bool isValidFrame(std::span< const uint8_t > bytes)
Definition RTCMFramer.h:63
static constexpr uint16_t MAX_FRAME_SIZE
Definition RTCMFramer.h:25
bool addByte(uint8_t byte)
Definition RTCMFramer.cc:21
static bool isValidFrame(QByteArrayView bytes)
Definition RTCMFramer.h:72
bool valid() const
Definition RTCMFramer.h:61
constexpr uint32_t crc24q(std::span< const uint8_t > bytes)
CRC-24Q: polynomial 0x1864CFB, initial value 0, no reflection and no final XOR.
Definition Checksums.h:40
QByteArray data
Definition RTCMFramer.h:93
qint64 receivedAtMs
Definition RTCMFramer.h:95