arduino-audio-tools
Loading...
Searching...
No Matches
HDLCStream.h
Go to the documentation of this file.
1#pragma once
2
3#include <stdbool.h>
4#include <stdint.h>
5
7#include "AudioToolsConfig.h"
8
9namespace audio_tools {
10
26class HDLCStream : public Stream {
27 public:
28 HDLCStream() = default;
29
30 HDLCStream(int maxFrameSize) {
31 resize(maxFrameSize);
32 }
40 HDLCStream(Stream& stream, size_t maxFrameSize) {
41 setStream(stream);
42 resize(maxFrameSize);
43 }
44
51 HDLCStream(Print& stream, size_t maxFrameSize) {
52 setPrint(stream);
53 resize(maxFrameSize);
54 }
55
56 void setStream(Stream& stream) {
57 p_stream = &stream;
58 p_print = &stream;
59 }
60
61 void setPrint(Print& stream) { p_print = &stream; }
62
68 int available() override {
71 }
72
78 int read() override { return -1; }
79
87 size_t readBytes(uint8_t* buffer, size_t length) {
89 size_t available_bytes = rx_frame_buffer.available();
90 // get more data
91 if (available_bytes == 0) {
93 available_bytes = rx_frame_buffer.available();
94 }
95
96 // check that we consume the full frame
97 if (length < available_bytes) {
98 LOGE("readBytes len too small %u instead of %u", (unsigned)length,
99 (unsigned)available_bytes);
100 return 0;
101 }
102
103 // provide the data
104 memcpy(buffer, rx_frame_buffer.data(), available_bytes);
106 _frameReady = false;
107 return available_bytes;
108 }
109
115 int peek() override { return -1; }
116
120 void flush() override { p_stream->flush(); }
121
128 size_t write(uint8_t b) override { return 0; }
129
137 size_t write(const uint8_t* data, size_t len) override {
139 return writeFrame(data, len);
140 }
141
142 bool resize(size_t size) {
143 if (size > _maxFrameSize) return false;
146 _rxBuffer.resize(size);
147 _maxFrameSize = size;
148 return true;
149 }
150
151 protected:
152 Stream* p_stream = nullptr;
153 Print* p_print = nullptr;
154 size_t _maxFrameSize = 0;
158 size_t _frameLen = 0;
159 size_t _rxLen = 0;
160 size_t _rxPos = 0;
161 bool _frameReady = false;
162
164
165 static constexpr uint8_t HDLC_FLAG = 0x7E;
166 static constexpr uint8_t HDLC_ESC = 0x7D;
167 static constexpr uint8_t HDLC_ESC_XOR = 0x20;
168
177 crc ^= (uint16_t)data << 8;
178 for (int i = 0; i < 8; i++)
179 crc = (crc & 0x8000) ? (crc << 1) ^ 0x1021 : (crc << 1);
180 return crc;
181 }
182
189 if (b == HDLC_FLAG || b == HDLC_ESC) {
192 } else {
194 }
195 }
196
204 size_t writeFrame(const uint8_t* data, size_t len) {
205 if (!data || len == 0) return 0;
206
207 uint16_t crc = 0xFFFF;
209
210 for (size_t i = 0; i < len; ++i) {
211 crc = _crc16(data[i], crc);
212 _writeEscaped(data[i]);
213 }
214
215 _writeEscaped(crc >> 8);
216 _writeEscaped(crc & 0xFF);
219 p_print->flush();
221 return len;
222 }
223
229 while (!_frameReady && p_stream->available()) {
230 uint8_t b = p_stream->read();
231
232 if (b == HDLC_FLAG) {
233 if (_rxLen >= 3) {
235 (_rxBuffer[_rxLen - 2] << 8) | _rxBuffer[_rxLen - 1];
236 uint16_t calcCrc = 0xFFFF;
237 for (size_t i = 0; i < _rxLen - 2; ++i)
239
240 if (calcCrc == recvCrc) {
241 for (int j = 0; j < _rxLen - 2; j++) {
243 }
244
245 _frameLen = _rxLen - 2;
246 _rxPos = 0;
247 _frameReady = true;
248 }
249 }
250 _rxState = IDLE;
251 _rxLen = 0;
252 continue;
253 }
254
255 switch (_rxState) {
256 case IDLE:
257 _rxLen = 0;
258 if (b == HDLC_ESC) {
260 } else {
263 }
264 break;
265
266 case RECEIVING:
267 if (b == HDLC_ESC) {
269 } else if (_rxLen < _maxFrameSize) {
270 _rxBuffer[_rxLen++] = b;
271 }
272 break;
273
274 case ESCAPED:
275 if (_rxLen < _maxFrameSize) {
277 }
279 break;
280 }
281
282 if (_rxLen >= _maxFrameSize) {
283 _rxState = IDLE; // overflow
284 _rxLen = 0;
285 }
286 }
287 }
288};
289
290} // namespace audio_tools
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define assert(T)
Definition avr.h:10
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
virtual void flush()
Definition Arduino.h:130
Definition Arduino.h:136
virtual int available()
Definition Arduino.h:139
void clear()
same as reset
Definition Buffers.h:96
High-Level Data Link Control (HDLC) is a bit-oriented code-transparent synchronous data link layer pr...
Definition HDLCStream.h:26
void flush() override
Flush the output buffer of the underlying stream.
Definition HDLCStream.h:120
void _processInput()
Process incoming bytes, detect frames, validate CRC and prepare data for reading.
Definition HDLCStream.h:228
static constexpr uint8_t HDLC_ESC_XOR
Definition HDLCStream.h:167
size_t _rxPos
Definition HDLCStream.h:160
void setStream(Stream &stream)
Definition HDLCStream.h:56
size_t readBytes(uint8_t *buffer, size_t length)
Read a full frame from the stream into a buffer.
Definition HDLCStream.h:87
int peek() override
Not supported.
Definition HDLCStream.h:115
enum audio_tools::HDLCStream::RxState _rxState
size_t write(uint8_t b) override
Not supported.
Definition HDLCStream.h:128
size_t _maxFrameSize
Definition HDLCStream.h:154
size_t writeFrame(const uint8_t *data, size_t len)
Write a complete HDLC frame with proper framing and CRC.
Definition HDLCStream.h:204
size_t _rxLen
Definition HDLCStream.h:159
int available() override
Get the number of bytes available to read from the frame buffer.
Definition HDLCStream.h:68
size_t write(const uint8_t *data, size_t len) override
Write multiple bytes to the stream.
Definition HDLCStream.h:137
Stream * p_stream
Definition HDLCStream.h:152
Vector< uint8_t > _rxBuffer
Definition HDLCStream.h:157
void _writeEscaped(uint8_t b)
Write a byte with proper HDLC byte stuffing if needed.
Definition HDLCStream.h:188
SingleBuffer< uint8_t > tx_frame_buffer
Definition HDLCStream.h:155
static constexpr uint8_t HDLC_FLAG
Definition HDLCStream.h:165
static constexpr uint8_t HDLC_ESC
Definition HDLCStream.h:166
HDLCStream(Print &stream, size_t maxFrameSize)
Construct a new HDLCStream object using a Print for output only.
Definition HDLCStream.h:51
SingleBuffer< uint8_t > rx_frame_buffer
Definition HDLCStream.h:156
size_t _frameLen
Definition HDLCStream.h:158
void setPrint(Print &stream)
Definition HDLCStream.h:61
uint16_t _crc16(uint8_t data, uint16_t crc)
Calculate CRC-CCITT (16-bit)
Definition HDLCStream.h:176
Print * p_print
Definition HDLCStream.h:153
int read() override
Not supported.
Definition HDLCStream.h:78
bool _frameReady
Definition HDLCStream.h:161
bool resize(size_t size)
Definition HDLCStream.h:142
HDLCStream(Stream &stream, size_t maxFrameSize)
Construct a new HDLCStream object using a Stream for input and output.
Definition HDLCStream.h:40
RxState
Definition HDLCStream.h:163
@ RECEIVING
Definition HDLCStream.h:163
@ ESCAPED
Definition HDLCStream.h:163
@ IDLE
Definition HDLCStream.h:163
HDLCStream(int maxFrameSize)
Definition HDLCStream.h:30
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:184
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:218
int available() override
provides the number of entries that are available to read
Definition Buffers.h:245
T * data()
Provides address of actual data.
Definition Buffers.h:296
bool resize(size_t size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:317
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:508