BNO08x Driver
API reference
Loading...
Searching...
No Matches
bno08x_shtp_uart.hpp
Go to the documentation of this file.
1#pragma once
30#include <cstddef>
31#include <cstdint>
32
34
36inline constexpr uint32_t BAUD_RATE = 3000000;
38inline constexpr uint32_t HOST_BYTE_GAP_US = 100;
39
40inline constexpr uint8_t FLAG = 0x7E;
41inline constexpr uint8_t ESCAPE = 0x7D;
42inline constexpr uint8_t ESCAPE_XOR = 0x20;
43inline constexpr uint8_t PROTOCOL_CONTROL = 0x00;
44inline constexpr uint8_t PROTOCOL_SHTP = 0x01;
45
47inline constexpr uint8_t BUFFER_STATUS_QUERY[3] = {FLAG, PROTOCOL_CONTROL, FLAG};
48
50constexpr std::size_t MaxEncodedSize(std::size_t payloadLen) noexcept {
51 return 2 * payloadLen + 3;
52}
53
63inline std::size_t EncodeFrame(const uint8_t* shtp, std::size_t len, uint8_t* out,
64 std::size_t cap) noexcept {
65 std::size_t n = 0;
66 auto put = [&](uint8_t b) {
67 if (n < cap) {
68 out[n] = b;
69 }
70 ++n;
71 };
72 put(FLAG);
73 put(PROTOCOL_SHTP);
74 for (std::size_t i = 0; i < len; ++i) {
75 const uint8_t b = shtp[i];
76 if (b == FLAG || b == ESCAPE) {
77 put(ESCAPE);
78 put(static_cast<uint8_t>(b ^ ESCAPE_XOR));
79 } else {
80 put(b);
81 }
82 }
83 put(FLAG);
84 return n <= cap ? n : 0;
85}
86
98template <std::size_t Capacity>
100public:
102 enum class Event : uint8_t {
103 None,
104 ShtpFrame,
106 Dropped
107 };
108
110 Event Push(uint8_t c) noexcept {
111 switch (state_) {
112 case State::Outside:
113 if (c == FLAG) {
114 startFrame();
115 }
116 return Event::None;
117 case State::Escaped:
118 store(static_cast<uint8_t>(c ^ ESCAPE_XOR));
119 state_ = State::Inside;
120 return Event::None;
121 case State::Inside:
122 break;
123 }
124 if (c == ESCAPE) {
125 state_ = State::Escaped;
126 return Event::None;
127 }
128 if (c != FLAG) {
129 store(c);
130 return Event::None;
131 }
132 // A flag closes the frame; it may also open the next one, so stay inside.
133 const Event ev = finishFrame();
134 startFrame();
135 return ev;
136 }
137
139 const uint8_t* Data() const noexcept {
140 return frame_ + 1;
141 }
142
144 std::size_t Size() const noexcept {
145 return shtpLen_;
146 }
147
149 uint16_t BufferSpace() const noexcept {
150 return bufferSpace_;
151 }
152
154 void ClearBufferSpace() noexcept {
155 bufferSpace_ = 0;
156 }
157
159 void Reset() noexcept {
160 state_ = State::Outside;
161 len_ = 0;
162 overflow_ = false;
163 shtpLen_ = 0;
164 bufferSpace_ = 0;
165 }
166
167private:
168 enum class State : uint8_t { Outside, Inside, Escaped };
169
170 void startFrame() noexcept {
171 state_ = State::Inside;
172 len_ = 0;
173 overflow_ = false;
174 }
175
176 void store(uint8_t c) noexcept {
177 if (len_ < Capacity) {
178 frame_[len_++] = c;
179 } else {
180 overflow_ = true;
181 }
182 }
183
184 Event finishFrame() noexcept {
185 if (len_ == 0) {
186 return Event::None; // two flags in a row: an empty frame, or a closing flag reused
187 }
188 if (overflow_) {
189 return Event::Dropped;
190 }
191 if (frame_[0] == PROTOCOL_SHTP) {
192 shtpLen_ = len_ - 1;
193 return Event::ShtpFrame;
194 }
195 if (frame_[0] == PROTOCOL_CONTROL && len_ >= 3) {
196 bufferSpace_ = static_cast<uint16_t>(frame_[1] | (frame_[2] << 8));
197 return Event::BufferStatus;
198 }
199 return Event::Dropped;
200 }
201
202 static_assert(Capacity >= 3, "a frame needs room for the protocol ID and a buffer status");
203
204 uint8_t frame_[Capacity]{};
205 std::size_t len_{0};
206 std::size_t shtpLen_{0};
207 uint16_t bufferSpace_{0};
208 bool overflow_{false};
209 State state_{State::Outside};
210};
211
212} // namespace bno08x::shtp_uart
Byte-at-a-time decoder for frames received from the hub.
Definition bno08x_shtp_uart.hpp:99
std::size_t Size() const noexcept
Length of the last SHTP transfer.
Definition bno08x_shtp_uart.hpp:144
Event Push(uint8_t c) noexcept
Feed one received byte.
Definition bno08x_shtp_uart.hpp:110
const uint8_t * Data() const noexcept
SHTP transfer of the last Event::ShtpFrame (header first).
Definition bno08x_shtp_uart.hpp:139
void ClearBufferSpace() noexcept
Forget the reported buffer space (the next frame needs a new query).
Definition bno08x_shtp_uart.hpp:154
void Reset() noexcept
Drop any partial frame and wait for the next flag.
Definition bno08x_shtp_uart.hpp:159
uint16_t BufferSpace() const noexcept
Free space the hub reported in its last Buffer Status Notification.
Definition bno08x_shtp_uart.hpp:149
Event
What the last byte completed.
Definition bno08x_shtp_uart.hpp:102
@ BufferStatus
A Buffer Status Notification updated BufferSpace().
@ Dropped
A frame was discarded (overflow or unknown protocol ID).
@ ShtpFrame
An SHTP transfer is in Data() / Size().
Definition bno08x_shtp_uart.hpp:33
constexpr uint32_t BAUD_RATE
UART-SHTP line rate: 3 Mbit/s, 8 data bits, no parity, 1 stop bit (datasheet 1.2.3....
Definition bno08x_shtp_uart.hpp:36
constexpr uint8_t PROTOCOL_SHTP
Protocol ID of SHTP transfers.
Definition bno08x_shtp_uart.hpp:44
constexpr std::size_t MaxEncodedSize(std::size_t payloadLen) noexcept
Largest frame EncodeFrame() can produce for payloadLen bytes (every byte escaped).
Definition bno08x_shtp_uart.hpp:50
constexpr uint8_t FLAG
Frame delimiter.
Definition bno08x_shtp_uart.hpp:40
constexpr uint32_t HOST_BYTE_GAP_US
Minimum spacing between bytes sent from the host to the hub, in µs (datasheet 1.2....
Definition bno08x_shtp_uart.hpp:38
constexpr uint8_t BUFFER_STATUS_QUERY[3]
Buffer Status Query, ready to send.
Definition bno08x_shtp_uart.hpp:47
std::size_t EncodeFrame(const uint8_t *shtp, std::size_t len, uint8_t *out, std::size_t cap) noexcept
Wrap one SHTP transfer (header included) in a UART-SHTP frame.
Definition bno08x_shtp_uart.hpp:63
constexpr uint8_t ESCAPE
Escape: the next byte is XOR ESCAPE_XOR.
Definition bno08x_shtp_uart.hpp:41
constexpr uint8_t ESCAPE_XOR
Value XORed into an escaped byte.
Definition bno08x_shtp_uart.hpp:42
constexpr uint8_t PROTOCOL_CONTROL
Protocol ID of control frames (BSQ / BSN).
Definition bno08x_shtp_uart.hpp:43