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:
34 HDLCStream(Stream& stream, size_t maxFrameSize)
35 : _maxFrameSize(maxFrameSize) {
36 p_stream = &stream;
37 p_print = &stream;
38 tx_frame_buffer.resize(maxFrameSize);
39 rx_frame_buffer.resize(maxFrameSize);
40 _rxBuffer.resize(maxFrameSize);
41 }
42
49 HDLCStream(Print& stream, size_t maxFrameSize) : _maxFrameSize(maxFrameSize) {
50 p_print = &stream;
51 tx_frame_buffer.resize(maxFrameSize);
52 rx_frame_buffer.resize(maxFrameSize);
53 _rxBuffer.resize(maxFrameSize);
54 }
55
61 int available() override {
64 }
65
71 int read() override { return -1; }
72
80 size_t readBytes(uint8_t* buffer, size_t length) override {
81 size_t available_bytes = rx_frame_buffer.available();
82 // get more data
83 if (available_bytes == 0) {
85 available_bytes = rx_frame_buffer.available();
86 }
87
88 // check that we consume the full frame
89 if (length < available_bytes) {
90 LOGE("readBytes len too small %u instead of %u", (unsigned)length,
91 (unsigned)available_bytes);
92 return 0;
93 }
94
95 // provide the data
96 memcpy(buffer, rx_frame_buffer.data(), available_bytes);
98 _frameReady = false;
99 return available_bytes;
100 }
101
107 int peek() override { return -1; }
108
112 void flush() override { p_stream->flush(); }
113
120 size_t write(uint8_t b) override { return 0; }
121
129 size_t write(const uint8_t* data, size_t len) override {
130 return writeFrame(data, len);
131 }
132
133 protected:
134 Stream* p_stream = nullptr;
135 Print* p_print = nullptr;
136 const size_t _maxFrameSize;
140 size_t _frameLen = 0;
141 size_t _rxLen = 0;
142 size_t _rxPos = 0;
143 bool _frameReady = false;
144
146
147 static constexpr uint8_t HDLC_FLAG = 0x7E;
148 static constexpr uint8_t HDLC_ESC = 0x7D;
149 static constexpr uint8_t HDLC_ESC_XOR = 0x20;
150
159 crc ^= (uint16_t)data << 8;
160 for (int i = 0; i < 8; i++)
161 crc = (crc & 0x8000) ? (crc << 1) ^ 0x1021 : (crc << 1);
162 return crc;
163 }
164
171 if (b == HDLC_FLAG || b == HDLC_ESC) {
174 } else {
176 }
177 }
178
186 size_t writeFrame(const uint8_t* data, size_t len) {
187 if (!data || len == 0) return 0;
188
189 uint16_t crc = 0xFFFF;
191
192 for (size_t i = 0; i < len; ++i) {
193 crc = _crc16(data[i], crc);
194 _writeEscaped(data[i]);
195 }
196
197 _writeEscaped(crc >> 8);
198 _writeEscaped(crc & 0xFF);
201 p_print->flush();
203 return len;
204 }
205
211 while (!_frameReady && p_stream->available()) {
212 uint8_t b = p_stream->read();
213
214 if (b == HDLC_FLAG) {
215 if (_rxLen >= 3) {
217 (_rxBuffer[_rxLen - 2] << 8) | _rxBuffer[_rxLen - 1];
218 uint16_t calcCrc = 0xFFFF;
219 for (size_t i = 0; i < _rxLen - 2; ++i)
221
222 if (calcCrc == recvCrc) {
223 for (int j = 0; j < _rxLen - 2; j++) {
225 }
226
227 _frameLen = _rxLen - 2;
228 _rxPos = 0;
229 _frameReady = true;
230 }
231 }
232 _rxState = IDLE;
233 _rxLen = 0;
234 continue;
235 }
236
237 switch (_rxState) {
238 case IDLE:
239 _rxLen = 0;
240 if (b == HDLC_ESC) {
242 } else {
245 }
246 break;
247
248 case RECEIVING:
249 if (b == HDLC_ESC) {
251 } else if (_rxLen < _maxFrameSize) {
252 _rxBuffer[_rxLen++] = b;
253 }
254 break;
255
256 case ESCAPED:
257 if (_rxLen < _maxFrameSize) {
259 }
261 break;
262 }
263
264 if (_rxLen >= _maxFrameSize) {
265 _rxState = IDLE; // overflow
266 _rxLen = 0;
267 }
268 }
269 }
270};
271
272} // namespace audio_tools
#define LOGE(...)
Definition AudioLoggerIDF.h:30
void clear()
same as reset
Definition Buffers.h:95
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:112
void _processInput()
Process incoming bytes, detect frames, validate CRC and prepare data for reading.
Definition HDLCStream.h:210
static constexpr uint8_t HDLC_ESC_XOR
Definition HDLCStream.h:149
size_t _rxPos
Definition HDLCStream.h:142
const size_t _maxFrameSize
Definition HDLCStream.h:136
int peek() override
Not supported.
Definition HDLCStream.h:107
enum audio_tools::HDLCStream::RxState _rxState
size_t readBytes(uint8_t *buffer, size_t length) override
Read a full frame from the stream into a buffer.
Definition HDLCStream.h:80
size_t write(uint8_t b) override
Not supported.
Definition HDLCStream.h:120
size_t writeFrame(const uint8_t *data, size_t len)
Write a complete HDLC frame with proper framing and CRC.
Definition HDLCStream.h:186
size_t _rxLen
Definition HDLCStream.h:141
int available() override
Get the number of bytes available to read from the frame buffer.
Definition HDLCStream.h:61
size_t write(const uint8_t *data, size_t len) override
Write multiple bytes to the stream.
Definition HDLCStream.h:129
Stream * p_stream
Definition HDLCStream.h:134
Vector< uint8_t > _rxBuffer
Definition HDLCStream.h:139
void _writeEscaped(uint8_t b)
Write a byte with proper HDLC byte stuffing if needed.
Definition HDLCStream.h:170
SingleBuffer< uint8_t > tx_frame_buffer
Definition HDLCStream.h:137
static constexpr uint8_t HDLC_FLAG
Definition HDLCStream.h:147
static constexpr uint8_t HDLC_ESC
Definition HDLCStream.h:148
HDLCStream(Print &stream, size_t maxFrameSize)
Construct a new HDLCStream object using a Print for output only.
Definition HDLCStream.h:49
SingleBuffer< uint8_t > rx_frame_buffer
Definition HDLCStream.h:138
size_t _frameLen
Definition HDLCStream.h:140
uint16_t _crc16(uint8_t data, uint16_t crc)
Calculate CRC-CCITT (16-bit)
Definition HDLCStream.h:158
Print * p_print
Definition HDLCStream.h:135
int read() override
Not supported.
Definition HDLCStream.h:71
bool _frameReady
Definition HDLCStream.h:143
HDLCStream(Stream &stream, size_t maxFrameSize)
Construct a new HDLCStream object using a Stream for input and output.
Definition HDLCStream.h:34
RxState
Definition HDLCStream.h:145
@ RECEIVING
Definition HDLCStream.h:145
@ ESCAPED
Definition HDLCStream.h:145
@ IDLE
Definition HDLCStream.h:145
Definition NoArduino.h:62
virtual size_t write(const uint8_t *data, size_t len)
Definition NoArduino.h:126
virtual void flush()
Definition NoArduino.h:136
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:172
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:206
int available() override
provides the number of entries that are available to read
Definition Buffers.h:233
bool resize(int size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:305
T * data()
Provides address of actual data.
Definition Buffers.h:284
Definition NoArduino.h:142
virtual int available()
Definition NoArduino.h:146
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(int 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:512