Skip to content

Commit c0f3e2f

Browse files
author
Richard Unger
committed
Buffer TextIO input to make non-blocking
1 parent 6c0db29 commit c0f3e2f

File tree

2 files changed

+100
-34
lines changed

2 files changed

+100
-34
lines changed

src/comms/streams/TextIO.cpp

Lines changed: 89 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -70,46 +70,78 @@ TextIO& TextIO::operator<<(Separator value) {
7070
return *this;
7171
};
7272

73-
#ifndef ESP32
74-
#define LOOKAHEADARGS LookaheadMode::SKIP_NONE
75-
#else
76-
#define LOOKAHEADARGS
77-
#endif
7873

79-
TextIO& TextIO::operator>>(float &value) {
80-
if (_io.peek() == '\n') {
81-
return *this; // TODO flag this error
74+
75+
uint32_t TextIO::intFromBuffer() {
76+
if (in_sep) {
77+
buffer_index++; // discard the separator
8278
}
79+
if (buffer_index >= buffer_len)
80+
in_sync = false;
81+
uint32_t value = 0;
82+
while (buffer_index < buffer_len) {
83+
char c = buffer[buffer_index];
84+
if (c >= '0' && c <= '9') {
85+
value = value * 10 + (c - '0');
86+
buffer_index++;
87+
}
88+
else {
89+
break;
90+
}
91+
}
92+
return value;
93+
}
94+
95+
96+
TextIO& TextIO::operator>>(float &value) {
8397
if (in_sep) {
84-
_io.read(); // discard the separator
98+
buffer_index++; // discard the separator
99+
in_sep = false;
100+
}
101+
if (buffer_index >= buffer_len) {
102+
in_sync = false;
103+
return *this;
104+
}
105+
char c = buffer[buffer_index];
106+
int8_t sign = 1;
107+
if (c == '-') {
108+
buffer_index++;
109+
sign = -1;
110+
}
111+
uint32_t val = 0;
112+
if (c != '.')
113+
val = intFromBuffer();
114+
if (buffer_index < buffer_len) {
115+
c = buffer[buffer_index];
116+
if (c == '.') {
117+
uint8_t pos = ++buffer_index;
118+
uint32_t frac = intFromBuffer();
119+
if (pos < buffer_index) {
120+
value = ((float)val + (float)frac / pow(10, buffer_index - pos)) * sign;
121+
in_sep = true;
122+
}
123+
else
124+
in_sync = false;
125+
return *this;
126+
}
85127
}
86-
value = _io.parseFloat(LOOKAHEADARGS); // TODO LookaheadMode is not defined on ESP32
128+
value = (float)val * sign;
87129
in_sep = true;
88130
return *this;
89131
};
90132

133+
134+
91135
TextIO& TextIO::operator>>(uint32_t &value) {
92-
if (_io.peek() == '\n') {
93-
return *this; // TODO flag this error
94-
}
95-
if (in_sep) {
96-
_io.read(); // discard the separator
97-
}
98-
value = (uint32_t)_io.parseInt(LOOKAHEADARGS);
136+
value = intFromBuffer();
99137
in_sep = true;
100138
return *this;
101139
};
102140

103141

104142

105143
TextIO& TextIO::operator>>(uint8_t &value) {
106-
if (_io.peek() == '\n') {
107-
return *this; // TODO flag this error
108-
}
109-
if (in_sep) {
110-
_io.read(); // discard the separator
111-
}
112-
value = (uint8_t)_io.parseInt(LOOKAHEADARGS);
144+
value = (uint8_t)intFromBuffer();
113145
in_sep = true;
114146
return *this;
115147
};
@@ -118,25 +150,48 @@ TextIO& TextIO::operator>>(uint8_t &value) {
118150

119151
TextIO& TextIO::operator>>(Packet &value) {
120152
while (!in_sync && _io.available() > 0) {
121-
if (_io.read() == '\n')
153+
if (_io.read() == '\n') {
122154
in_sync = true;
155+
buffer_len = 0;
156+
}
123157
}
124-
if (_io.peek() == '\n') {
125-
_io.read(); // discard the \n
158+
if (buffer_index >= buffer_len) {
159+
buffer_len = 0;
160+
buffer_index = 0;
126161
}
127-
if (!in_sync || _io.available() < 3) { // frame type, register id, \n to end frame = 3 bytes minimum frame size
128-
value.type = 0x00;
129-
value.payload_size = 0;
130-
return *this;
162+
while (in_sync && _io.available()>0) {
163+
uint8_t peek = _io.peek();
164+
if (peek == '\n' || peek == '\r') {
165+
// skip newlines and carriage returns
166+
while (_io.available()>0 && (peek == '\n' || peek == '\r')) {
167+
_io.read(); // discard the \n
168+
peek = _io.peek();
169+
}
170+
if (buffer_len>1) {
171+
value.type = buffer[0];
172+
value.payload_size = 0;
173+
in_sep = false;
174+
buffer_index = 1;
175+
return *this;
176+
}
177+
}
178+
else {
179+
if (buffer_len < SIMPLEFOC_TEXTIO_BUFFER_SIZE)
180+
buffer[buffer_len++] = _io.read();
181+
else {
182+
buffer_len = 0;
183+
in_sync = false;
184+
}
185+
}
131186
}
132-
value.type = _io.read();
187+
188+
value.type = 0x00;
133189
value.payload_size = 0;
134-
in_sep = false;
135190
return *this;
136191
};
137192

138193

139194

140195
bool TextIO::is_complete() {
141-
return _io.peek() == '\n';
196+
return buffer_index >= buffer_len;
142197
};

src/comms/streams/TextIO.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
#include <Stream.h>
77

88

9+
#ifndef SIMPLEFOC_TEXTIO_BUFFER_SIZE
10+
#define SIMPLEFOC_TEXTIO_BUFFER_SIZE 64
11+
#endif
12+
13+
14+
915
class TextIO : public PacketIO {
1016
public:
1117
TextIO(Stream& io);
@@ -24,9 +30,14 @@ class TextIO : public PacketIO {
2430

2531
uint8_t precision = 4;
2632
protected:
33+
uint32_t intFromBuffer();
34+
2735
Stream& _io;
2836
bool sep = false;
2937
bool in_sep = false;
38+
uint8_t buffer_index = 0;
39+
uint8_t buffer_len = 0;
40+
char buffer[SIMPLEFOC_TEXTIO_BUFFER_SIZE];
3041
};
3142

3243

0 commit comments

Comments
 (0)