CodexPadFrameDecoder Arduino 库 1.0.3
载入中...
搜索中...
未找到
robust_frame.cpp
1#include "robust_frame.h"
2
3#include "crc8.h"
4
5namespace robust_frame {
6namespace {
7constexpr size_t kMinUnescapedSize = 2;
8
9constexpr uint8_t kFrameHeader = 0xAA;
10constexpr uint8_t kFrameFooter = 0x55;
11constexpr uint8_t kEscapeChar = 0xDB;
12constexpr uint8_t kXorEscape = 0x20;
13
14constexpr bool CheckXorOperator() {
15 return ((kFrameHeader ^ kXorEscape) != kFrameHeader && (kFrameHeader ^ kXorEscape) != kFrameFooter && (kFrameHeader ^ kXorEscape) != kEscapeChar) &&
16 ((kFrameFooter ^ kXorEscape) != kFrameHeader && (kFrameFooter ^ kXorEscape) != kFrameFooter && (kFrameFooter ^ kXorEscape) != kEscapeChar) &&
17 ((kEscapeChar ^ kXorEscape) != kFrameHeader && (kEscapeChar ^ kXorEscape) != kFrameFooter && (kEscapeChar ^ kXorEscape) != kEscapeChar);
18}
19
20static_assert(CheckXorOperator(), "XOR operator 0x20 is not safe");
21} // namespace
22
23Parser::Parser(const size_t max_payload_size, FrameCallback callback, void *user_data)
24 : max_payload_size_(max_payload_size + 1), callback_(callback), user_data_(user_data), buffer_(new uint8_t[max_payload_size_]) {
25}
26
28 delete[] buffer_;
29}
30
31void Parser::Feed(const uint8_t byte) {
32 switch (state_) {
33 case State::kSyncHeader: {
34 if (byte == kFrameHeader) {
35 buffer_len_ = 0;
36 state_ = State::kCollectPayload;
37 }
38 break;
39 }
40 case State::kCollectPayload: {
41 if (byte == kFrameFooter) {
42 if (buffer_len_ >= kMinUnescapedSize && crc8::Calculate(buffer_, static_cast<size_t>(buffer_len_ - 1)) == buffer_[buffer_len_ - 1]) {
43 if (callback_) {
44 callback_(buffer_, user_data_);
45 }
46 }
47 Reset();
48 } else if (byte == kEscapeChar) {
49 state_ = State::kUnescape;
50 } else if (byte == kFrameHeader || buffer_len_ == max_payload_size_) {
51 Reset();
52 Feed(byte);
53 } else if (buffer_len_ < max_payload_size_) {
54 buffer_[buffer_len_++] = byte;
55 } else {
56 Reset();
57 }
58 break;
59 }
60 case State::kUnescape: {
61 const uint8_t unescaped = byte ^ kXorEscape;
62 if (unescaped != kFrameHeader && unescaped != kFrameFooter && unescaped != kEscapeChar) {
63 Reset();
64 Feed(byte);
65 } else if (buffer_len_ < max_payload_size_) {
66 buffer_[buffer_len_++] = unescaped;
67 state_ = State::kCollectPayload;
68 } else {
69 Reset();
70 }
71 break;
72 }
73 default: {
74 Reset();
75 break;
76 }
77 }
78}
79
80void Parser::Reset() {
81 state_ = State::kSyncHeader;
82 buffer_len_ = 0;
83}
84} // namespace robust_frame
void(*)(const uint8_t *data, void *user_data) FrameCallback
帧解析回调函数类型。
~Parser()
析构函数,释放内部动态分配的缓冲区。
Parser(const size_t max_payload_size, FrameCallback callback, void *user_data)
构造函数,根据最大载荷长度动态分配内部缓冲区。
void Feed(const uint8_t byte)
处理单个字节的核心状态机。
uint8_t Calculate(const uint8_t *data, const size_t size)
计算数据的 CRC-8 校验值(SAE J1850 标准)。