Skip to content

Commit 7826def

Browse files
committed
Use millis() for timeout over cycles - prefer long blocking over performance because user has
a choice. Fixed repeater example after all this time. Loopback example defaults to datarate that works over a real wire board to board (ESP8266, ESP32, mix).
1 parent 28263fa commit 7826def

File tree

4 files changed

+106
-76
lines changed

4 files changed

+106
-76
lines changed

examples/loopback/loopback.ino

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@
2525
#endif
2626

2727
// Pick only one of HWLOOPBACK, HWSOURCESWSINK, or HWSOURCESINK
28-
#define HWLOOPBACK 1
28+
//#define HWLOOPBACK 1
2929
//#define HWSOURCESWSINK 1
3030
//#define HWSOURCESINK 1
3131
#define HALFDUPLEX 1
3232

3333
#ifdef ESP32
34-
constexpr int IUTBITRATE = 57600;
34+
constexpr int IUTBITRATE = 19200;
3535
#else
36-
constexpr int IUTBITRATE = 153600;
36+
constexpr int IUTBITRATE = 19200;
3737
#endif
3838

3939
#if defined(ESP8266)
@@ -94,7 +94,13 @@ void setup() {
9494
Serial.setRxBufferSize(2 * BLOCKSIZE);
9595
logger.begin(9600, SWSERIAL_8N1, -1, TX);
9696
#else
97-
Serial.begin(9600);
97+
logger.begin(9600);
98+
#endif
99+
#if !defined(HWSOURCESINK)
100+
serialIUT.begin(IUTBITRATE, swSerialConfig, D5, D6, invert, 2 * BLOCKSIZE);
101+
#ifdef HALFDUPLEX
102+
serialIUT.enableIntTx(false);
103+
#endif
98104
#endif
99105
#elif defined(ESP32)
100106
#if defined(HWLOOPBACK) || defined(HWSOURCESWSINK)
@@ -108,22 +114,15 @@ void setup() {
108114
#else
109115
Serial.begin(9600);
110116
#endif
111-
#else
112-
Serial.begin(9600);
113-
#endif
114-
115117
#if !defined(HWSOURCESINK)
116-
#if defined(ESP8266)
117-
serialIUT.begin(IUTBITRATE, swSerialConfig, D5, D6, invert, 4 * BLOCKSIZE);
118-
#ifdef HALFDUPLEX
119-
serialIUT.enableIntTx(false);
120-
#endif
121-
#elif defined(ESP32)
122118
serialIUT.begin(IUTBITRATE, swSerialConfig, D5, D6, invert, 2 * BLOCKSIZE);
123119
#ifdef HALFDUPLEX
124120
serialIUT.enableIntTx(false);
125121
#endif
122+
#endif
126123
#else
124+
Serial.begin(9600);
125+
#if !defined(HWSOURCESINK)
127126
serialIUT.begin(IUTBITRATE);
128127
#endif
129128
#endif
@@ -133,6 +132,7 @@ void setup() {
133132
rxCount = 0;
134133
rxErrors = 0;
135134
rxParityErrors = 0;
135+
expected = -1;
136136

137137
logger.println("Loopback example for EspSoftwareSerial");
138138
}
@@ -141,9 +141,9 @@ unsigned char c = 0;
141141

142142
void loop() {
143143
#ifdef HALFDUPLEX
144-
unsigned char block[2 * BLOCKSIZE];
144+
char block[BLOCKSIZE];
145145
#endif
146-
unsigned char inBuf[2 * BLOCKSIZE];
146+
char inBuf[BLOCKSIZE];
147147
for (int i = 0; i < BLOCKSIZE; ++i) {
148148
#ifndef HALFDUPLEX
149149
#ifdef HWSOURCESWSINK
@@ -154,7 +154,7 @@ void loop() {
154154
#ifdef HWLOOPBACK
155155
int avail = hwSerial.available();
156156
while ((0 == (i % 8)) && avail > 0) {
157-
int inCnt = hwSerial.readBytes(inBuf, min(avail, min(BLOCKSIZE, hwSerial.availableForWrite())));
157+
int inCnt = hwSerial.read(inBuf, min(avail, min(BLOCKSIZE, hwSerial.availableForWrite())));
158158
hwSerial.write(inBuf, inCnt);
159159
avail -= inCnt;
160160
}
@@ -187,9 +187,9 @@ void loop() {
187187
// starting deadline for the first bytes to become readable
188188
deadlineStart = ESP.getCycleCount();
189189
inCnt = 0;
190-
while ((ESP.getCycleCount() - deadlineStart) < (1000000 * 10 * BLOCKSIZE) / IUTBITRATE * 8 * ESP.getCpuFreqMHz()) {
190+
while ((ESP.getCycleCount() - deadlineStart) < (1000000UL * 12 * BLOCKSIZE) / IUTBITRATE * 24 * ESP.getCpuFreqMHz()) {
191191
int avail = hwSerial.available();
192-
inCnt += hwSerial.readBytes(&inBuf[inCnt], min(avail, min(BLOCKSIZE - inCnt, hwSerial.availableForWrite())));
192+
inCnt += hwSerial.read(&inBuf[inCnt], min(avail, min(BLOCKSIZE - inCnt, hwSerial.availableForWrite())));
193193
if (inCnt >= BLOCKSIZE) { break; }
194194
// wait for more outstanding bytes to trickle in
195195
if (avail) deadlineStart = ESP.getCycleCount();
@@ -200,16 +200,24 @@ void loop() {
200200
// starting deadline for the first bytes to come in
201201
deadlineStart = ESP.getCycleCount();
202202
inCnt = 0;
203-
while ((ESP.getCycleCount() - deadlineStart) < (1000000 * 10 * BLOCKSIZE) / IUTBITRATE * 2 * ESP.getCpuFreqMHz()) {
204-
int avail = serialIUT.available();
203+
while ((ESP.getCycleCount() - deadlineStart) < (1000000UL * 12 * BLOCKSIZE) / IUTBITRATE * 8 * ESP.getCpuFreqMHz()) {
204+
int avail;
205+
if (0 != (swSerialConfig & 070))
206+
avail = serialIUT.available();
207+
else
208+
avail = serialIUT.read(inBuf, BLOCKSIZE);
205209
for (int i = 0; i < avail; ++i)
206210
{
207-
unsigned char r = serialIUT.read();
211+
unsigned char r;
212+
if (0 != (swSerialConfig & 070))
213+
r = serialIUT.read();
214+
else
215+
r = inBuf[i];
208216
if (expected == -1) { expected = r; }
209217
else {
210-
expected = (expected + 1) % 256;
218+
expected = (expected + 1) % (1UL << (5 + swSerialConfig % 4));
211219
}
212-
if (r != (expected & ((1 << (5 + swSerialConfig % 4)) - 1))) {
220+
if (r != expected) {
213221
++rxErrors;
214222
expected = -1;
215223
}
@@ -251,7 +259,8 @@ void loop() {
251259
rxParityErrors = 0;
252260
expected = -1;
253261
// resync
254-
delay(static_cast<uint32_t>(1000 * 10 * BLOCKSIZE / IUTBITRATE * 16));
262+
delay(1000UL * 12 * BLOCKSIZE / IUTBITRATE * 16);
263+
serialIUT.flush();
255264
start = micros();
256265
}
257266
}

examples/repeater/repeater.ino

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,110 +17,132 @@
1717
#define TX (1)
1818
#endif
1919

20-
//#define HWLOOPBACK 1
21-
//#define HALFDUPLEX 1
20+
#define HWLOOPBACK 1
21+
#define HALFDUPLEX 1
2222

2323
#ifdef ESP32
24-
constexpr int IUTBITRATE = 57600;
24+
constexpr int IUTBITRATE = 19200;
2525
#else
26-
constexpr int IUTBITRATE = 153600;
26+
constexpr int IUTBITRATE = 19200;
2727
#endif
2828

29-
constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8N1;
29+
#if defined(ESP8266)
30+
constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8E1;
31+
constexpr SerialConfig hwSerialConfig = SERIAL_8E1;
32+
#elif defined(ESP32)
33+
constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8E1;
34+
constexpr uint32_t hwSerialConfig = SERIAL_8E1;
35+
#else
36+
constexpr unsigned swSerialConfig = 3;
37+
#endif
38+
constexpr bool invert = false;
3039

3140
constexpr int BLOCKSIZE = 16; // use fractions of 256
3241

33-
3442
unsigned long start;
3543
String bitRateTxt("Effective data rate: ");
3644
int rxCount;
3745
int seqErrors;
3846
int expected;
3947
constexpr int ReportInterval = IUTBITRATE / 8;
4048

41-
#ifdef HWLOOPBACK
4249
#if defined(ESP8266)
50+
#if defined(HWLOOPBACK)
4351
HardwareSerial& repeater(Serial);
4452
SoftwareSerial logger;
45-
#elif defined(ESP32)
46-
HardwareSerial& repeater(Serial2);
53+
#else
54+
SoftwareSerial repeater;
4755
HardwareSerial& logger(Serial);
4856
#endif
57+
#elif defined(ESP32)
58+
#if defined(HWLOOPBACK)
59+
HardwareSerial& repeater(Serial2);
4960
#else
5061
SoftwareSerial repeater;
62+
#endif
63+
HardwareSerial& logger(Serial);
64+
#else
65+
SoftwareSerial repeater(14, 12);
5166
HardwareSerial& logger(Serial);
5267
#endif
5368

5469
void setup() {
55-
#ifdef HWLOOPBACK
5670
#if defined(ESP8266)
57-
repeater.begin(IUTBITRATE);
58-
repeater.setRxBufferSize(2 * BLOCKSIZE);
71+
#if defined(HWLOOPBACK)
72+
repeater.begin(IUTBITRATE, hwSerialConfig, SERIAL_FULL, 1, invert);
5973
repeater.swap();
60-
logger.begin(9600, swSerialConfig, RX, TX);
61-
#elif defined(ESP32)
62-
repeater.begin(IUTBITRATE, SERIAL_8N1, D7, D8);
6374
repeater.setRxBufferSize(2 * BLOCKSIZE);
75+
logger.begin(9600, SWSERIAL_8N1, -1, TX);
76+
#else
77+
repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, invert, 4 * BLOCKSIZE);
78+
#ifdef HALFDUPLEX
79+
repeater.enableIntTx(false);
80+
#endif
6481
logger.begin(9600);
6582
#endif
66-
#else
67-
#if defined(ESP8266)
68-
repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, false, 2 * BLOCKSIZE);
6983
#elif defined(ESP32)
70-
repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, false, 2 * BLOCKSIZE);
71-
#endif
84+
#if defined(HWLOOPBACK)
85+
repeater.begin(IUTBITRATE, hwSerialConfig, D7, D8, invert);
86+
repeater.setRxBufferSize(2 * BLOCKSIZE);
87+
logger.begin(9600);
88+
#else
89+
repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, invert, 4 * BLOCKSIZE);
7290
#ifdef HALFDUPLEX
7391
repeater.enableIntTx(false);
7492
#endif
7593
Serial.begin(9600);
7694
#endif
95+
#else
96+
repeater.begin(IUTBITRATE);
97+
Serial.begin(9600);
98+
#endif
7799

78100
start = micros();
79101
rxCount = 0;
80102
seqErrors = 0;
103+
expected = -1;
104+
105+
logger.println("Repeater example for EspSoftwareSerial");
81106
}
82107

83108
void loop() {
84109
#ifdef HALFDUPLEX
85-
unsigned char block[BLOCKSIZE];
110+
char block[BLOCKSIZE];
86111
#endif
87112
// starting deadline for the first bytes to come in
88113
uint32_t deadlineStart = ESP.getCycleCount();
89114
int inCnt = 0;
90-
while ((ESP.getCycleCount() - deadlineStart) < (1000000 * 10 * BLOCKSIZE) / IUTBITRATE * 2 * ESP.getCpuFreqMHz()) {
91-
int avail = repeater.available();
92-
for (int i = 0; i < avail; ++i)
93-
{
94-
int r = repeater.read();
95-
if (r == -1) { logger.println("read() == -1"); }
96-
if (expected == -1) { expected = r; }
97-
else {
98-
expected = (expected + 1) % 256;
99-
}
100-
if (r != (expected & ((1 << (5 + swSerialConfig % 4)) - 1))) {
101-
++seqErrors;
102-
expected = -1;
103-
}
104-
++rxCount;
115+
while ((ESP.getCycleCount() - deadlineStart) < (1000000UL * 12 * BLOCKSIZE) / IUTBITRATE * 24 * ESP.getCpuFreqMHz()) {
116+
int avail = repeater.available();
117+
for (int i = 0; i < avail; ++i)
118+
{
119+
int r = repeater.read();
120+
if (r == -1) { logger.println("read() == -1"); }
121+
if (expected == -1) { expected = r; }
122+
else {
123+
expected = (expected + 1) % (1UL << (5 + swSerialConfig % 4));
124+
}
125+
if (r != expected) {
126+
++seqErrors;
127+
expected = -1;
128+
}
129+
++rxCount;
105130
#ifdef HALFDUPLEX
106-
block[inCnt] = r;
131+
block[inCnt] = r;
107132
#else
108-
repeater.write(r);
133+
repeater.write(r);
109134
#endif
110-
}
111-
if (++inCnt >= BLOCKSIZE) { break; }
112-
// wait for more outstanding bytes to trickle in
113-
if (avail) deadlineStart = ESP.getCycleCount();
135+
if (++inCnt >= BLOCKSIZE) { break; }
136+
}
137+
if (inCnt >= BLOCKSIZE) { break; }
138+
// wait for more outstanding bytes to trickle in
139+
if (avail) deadlineStart = ESP.getCycleCount();
114140
}
115141

116142
#ifdef HALFDUPLEX
117143
repeater.write(block, inCnt);
118144
#endif
119145

120-
if (inCnt != 0 && inCnt != BLOCKSIZE) {
121-
logger.print("Got "); logger.print(inCnt); logger.println(" bytes during buffer interval");
122-
}
123-
124146
if (rxCount >= ReportInterval) {
125147
auto end = micros();
126148
unsigned long interval = end - start;

src/SoftwareSerial.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,12 @@ size_t SoftwareSerial::read(uint8_t * buffer, size_t size) {
207207
size_t SoftwareSerial::readBytes(uint8_t * buffer, size_t size) {
208208
if (!m_rxValid || !size) { return 0; }
209209
size_t count = 0;
210-
const auto timeout = _timeout * ESP.getCpuFreqMHz() * 1000UL;
211-
const auto start = ESP.getCycleCount();
210+
const auto start = millis();
212211
do {
213212
count += read(&buffer[count], size - count);
214213
if (count >= size) break;
215214
yield();
216-
} while (ESP.getCycleCount() - start < timeout);
215+
} while (millis() - start < _timeout);
217216
return count;
218217
}
219218

src/SoftwareSerial.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,10 @@ class SoftwareSerial : public Stream {
157157
return read(reinterpret_cast<uint8_t*>(buffer), size);
158158
}
159159
/// @returns The number of bytes read into buffer, up to size. Times out if the limit set through
160-
/// Stream::setTimeout() is reached. The maximum permissible timeout at 80MHz CPU freq. is ~26s.
160+
/// Stream::setTimeout() is reached.
161161
size_t readBytes(uint8_t* buffer, size_t size) override;
162162
/// @returns The number of bytes read into buffer, up to size. Times out if the limit set through
163-
/// Stream::setTimeout() is reached. The maximum permissible timeout at 80MHz CPU freq. is ~26s.
163+
/// Stream::setTimeout() is reached.
164164
size_t readBytes(char* buffer, size_t size) override {
165165
return readBytes(reinterpret_cast<uint8_t*>(buffer), size);
166166
}

0 commit comments

Comments
 (0)