1
- #include " AudioToolsConfig.h"
2
- #include " AudioTools/CoreAudio/Buffers.h"
3
1
#include < stdbool.h>
4
2
#include < stdint.h>
5
3
4
+ #include " AudioTools/CoreAudio/Buffers.h"
5
+ #include " AudioToolsConfig.h"
6
+
6
7
// / HDLC Asynchronous framing: The frame boundary octet is 01111110, (7E in
7
8
// / hexadecimal notation)
8
9
#define FRAME_BOUNDARY_OCTET 0x7E
20
21
#define CRC16_CCITT_INIT_VAL 0xFFFF
21
22
22
23
// / 16bit low and high bytes copier
23
- #define low (x ) ((x)& 0xFF )
24
+ #define low (x ) ((x) & 0xFF )
24
25
#define high (x ) (((x) >> 8 ) & 0xFF )
25
- #define lo8 (x ) ((x)& 0xff )
26
+ #define lo8 (x ) ((x) & 0xff )
26
27
#define hi8 (x ) ((x) >> 8 )
27
28
28
29
namespace audio_tools {
29
30
31
+ enum class HDLCWriteLogic { OnBufferFull, OnFlush, onWrite };
32
+
30
33
/* *
31
34
* @brief High-Level Data Link Control (HDLC) is a bit-oriented code-transparent
32
- * synchronous data link layer protocol
35
+ * synchronous data link layer protocol in scenarios where you need reliable,
36
+ * framed, and error-checked communication between devices at the data link
37
+ * layer.
38
+ *
33
39
* @ingroup communications
40
+ * @author Phil Schatzmann
34
41
*/
35
42
36
43
class HDLCStream : public Stream {
37
- public:
44
+ public:
38
45
// / Defines the output for the hdlc encoding
39
46
HDLCStream (Print &out, uint16_t max_frame_length) {
40
47
setOutput (out);
@@ -69,21 +76,38 @@ class HDLCStream : public Stream {
69
76
size_t write (const uint8_t *data, size_t len) override {
70
77
LOGD (" HDLCStream::write: %zu" , len);
71
78
72
- for (int j = 0 ; j < len; j++) {
73
- bool ok = frame_buffer.write (data[j]);
74
- assert (ok);
75
- if (frame_buffer.available () == max_frame_length) {
76
- sendFrame (frame_buffer.data (), max_frame_length);
77
- frame_buffer.reset ();
78
- }
79
+ switch (write_logic) {
80
+ case HDLCWriteLogic::OnBufferFull:
81
+ for (int j = 0 ; j < len; j++) {
82
+ bool ok = frame_buffer.write (data[j]);
83
+ assert (ok);
84
+ if (frame_buffer.available () == max_frame_length) {
85
+ sendFrame (frame_buffer.data (), max_frame_length);
86
+ frame_buffer.reset ();
87
+ }
88
+ }
89
+ break ;
90
+ case HDLCWriteLogic::onWrite:
91
+ sendFrame (data, len);
92
+ break ;
79
93
}
94
+
80
95
return len;
81
96
}
82
97
83
- int available () override {
84
- return p_in == nullptr ? 0 : max_frame_length;
98
+ void flush () override {
99
+ LOGD (" HDLCStream::flush" );
100
+ if (frame_buffer.available () > 0 ) {
101
+ sendFrame (frame_buffer.data (), frame_buffer.available ());
102
+ frame_buffer.reset ();
103
+ }
104
+ if (p_out != nullptr ) {
105
+ p_out->flush ();
106
+ }
85
107
}
86
108
109
+ int available () override { return p_in == nullptr ? 0 : max_frame_length; }
110
+
87
111
// / Provides the decoded data
88
112
size_t readBytes (uint8_t *data, size_t len) override {
89
113
if (p_in == nullptr ) {
@@ -96,7 +120,7 @@ class HDLCStream : public Stream {
96
120
while (result == 0 ) {
97
121
int ch = p_in->read ();
98
122
// ch is -1 when no data
99
- if (ch >= 0 ){
123
+ if (ch >= 0 ) {
100
124
result = charReceiver (ch);
101
125
if (result > 0 ) {
102
126
result = frame_buffer.readArray (data, result);
@@ -108,7 +132,6 @@ class HDLCStream : public Stream {
108
132
}
109
133
LOGD (" HDLCStream::readBytes: %zu -> %d" , len, result);
110
134
return result;
111
- ;
112
135
}
113
136
114
137
void setStream (Stream &io) {
@@ -133,7 +156,10 @@ class HDLCStream : public Stream {
133
156
// / not supported
134
157
int peek () override { return -1 ; }
135
158
136
- private:
159
+ // / Defines the framing logic for writing data
160
+ void setWriteLogic (HDLCWriteLogic logic) { write_logic = logic; }
161
+
162
+ private:
137
163
Print *p_out = nullptr ;
138
164
Stream *p_in = nullptr ;
139
165
bool escape_character = false ;
@@ -142,8 +168,10 @@ class HDLCStream : public Stream {
142
168
// 16bit CRC sum for _crc_ccitt_update
143
169
uint16_t frame_checksum;
144
170
uint16_t max_frame_length;
171
+ HDLCWriteLogic write_logic = HDLCWriteLogic::OnBufferFull;
145
172
146
- // / Function to find valid HDLC frame from incoming data: returns the available result bytes in the buffer
173
+ // / Function to find valid HDLC frame from incoming data: returns the
174
+ // / available result bytes in the buffer
147
175
int charReceiver (uint8_t data) {
148
176
int result = 0 ;
149
177
uint8_t *frame_buffer_data = frame_buffer.address ();
@@ -270,4 +298,4 @@ class HDLCStream : public Stream {
270
298
}
271
299
};
272
300
273
- } // namespace audio_tools
301
+ } // namespace audio_tools
0 commit comments