Skip to content

Commit

Permalink
Use millis() for timeout over cycles - prefer long blocking over perf…
Browse files Browse the repository at this point in the history
…ormance 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).
  • Loading branch information
dok-net committed Dec 19, 2019
1 parent 28263fa commit 7826def
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 76 deletions.
59 changes: 34 additions & 25 deletions examples/loopback/loopback.ino
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
#endif

// Pick only one of HWLOOPBACK, HWSOURCESWSINK, or HWSOURCESINK
#define HWLOOPBACK 1
//#define HWLOOPBACK 1
//#define HWSOURCESWSINK 1
//#define HWSOURCESINK 1
#define HALFDUPLEX 1

#ifdef ESP32
constexpr int IUTBITRATE = 57600;
constexpr int IUTBITRATE = 19200;
#else
constexpr int IUTBITRATE = 153600;
constexpr int IUTBITRATE = 19200;
#endif

#if defined(ESP8266)
Expand Down Expand Up @@ -94,7 +94,13 @@ void setup() {
Serial.setRxBufferSize(2 * BLOCKSIZE);
logger.begin(9600, SWSERIAL_8N1, -1, TX);
#else
Serial.begin(9600);
logger.begin(9600);
#endif
#if !defined(HWSOURCESINK)
serialIUT.begin(IUTBITRATE, swSerialConfig, D5, D6, invert, 2 * BLOCKSIZE);
#ifdef HALFDUPLEX
serialIUT.enableIntTx(false);
#endif
#endif
#elif defined(ESP32)
#if defined(HWLOOPBACK) || defined(HWSOURCESWSINK)
Expand All @@ -108,22 +114,15 @@ void setup() {
#else
Serial.begin(9600);
#endif
#else
Serial.begin(9600);
#endif

#if !defined(HWSOURCESINK)
#if defined(ESP8266)
serialIUT.begin(IUTBITRATE, swSerialConfig, D5, D6, invert, 4 * BLOCKSIZE);
#ifdef HALFDUPLEX
serialIUT.enableIntTx(false);
#endif
#elif defined(ESP32)
serialIUT.begin(IUTBITRATE, swSerialConfig, D5, D6, invert, 2 * BLOCKSIZE);
#ifdef HALFDUPLEX
serialIUT.enableIntTx(false);
#endif
#endif
#else
Serial.begin(9600);
#if !defined(HWSOURCESINK)
serialIUT.begin(IUTBITRATE);
#endif
#endif
Expand All @@ -133,6 +132,7 @@ void setup() {
rxCount = 0;
rxErrors = 0;
rxParityErrors = 0;
expected = -1;

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

void loop() {
#ifdef HALFDUPLEX
unsigned char block[2 * BLOCKSIZE];
char block[BLOCKSIZE];
#endif
unsigned char inBuf[2 * BLOCKSIZE];
char inBuf[BLOCKSIZE];
for (int i = 0; i < BLOCKSIZE; ++i) {
#ifndef HALFDUPLEX
#ifdef HWSOURCESWSINK
Expand All @@ -154,7 +154,7 @@ void loop() {
#ifdef HWLOOPBACK
int avail = hwSerial.available();
while ((0 == (i % 8)) && avail > 0) {
int inCnt = hwSerial.readBytes(inBuf, min(avail, min(BLOCKSIZE, hwSerial.availableForWrite())));
int inCnt = hwSerial.read(inBuf, min(avail, min(BLOCKSIZE, hwSerial.availableForWrite())));
hwSerial.write(inBuf, inCnt);
avail -= inCnt;
}
Expand Down Expand Up @@ -187,9 +187,9 @@ void loop() {
// starting deadline for the first bytes to become readable
deadlineStart = ESP.getCycleCount();
inCnt = 0;
while ((ESP.getCycleCount() - deadlineStart) < (1000000 * 10 * BLOCKSIZE) / IUTBITRATE * 8 * ESP.getCpuFreqMHz()) {
while ((ESP.getCycleCount() - deadlineStart) < (1000000UL * 12 * BLOCKSIZE) / IUTBITRATE * 24 * ESP.getCpuFreqMHz()) {
int avail = hwSerial.available();
inCnt += hwSerial.readBytes(&inBuf[inCnt], min(avail, min(BLOCKSIZE - inCnt, hwSerial.availableForWrite())));
inCnt += hwSerial.read(&inBuf[inCnt], min(avail, min(BLOCKSIZE - inCnt, hwSerial.availableForWrite())));
if (inCnt >= BLOCKSIZE) { break; }
// wait for more outstanding bytes to trickle in
if (avail) deadlineStart = ESP.getCycleCount();
Expand All @@ -200,16 +200,24 @@ void loop() {
// starting deadline for the first bytes to come in
deadlineStart = ESP.getCycleCount();
inCnt = 0;
while ((ESP.getCycleCount() - deadlineStart) < (1000000 * 10 * BLOCKSIZE) / IUTBITRATE * 2 * ESP.getCpuFreqMHz()) {
int avail = serialIUT.available();
while ((ESP.getCycleCount() - deadlineStart) < (1000000UL * 12 * BLOCKSIZE) / IUTBITRATE * 8 * ESP.getCpuFreqMHz()) {
int avail;
if (0 != (swSerialConfig & 070))
avail = serialIUT.available();
else
avail = serialIUT.read(inBuf, BLOCKSIZE);
for (int i = 0; i < avail; ++i)
{
unsigned char r = serialIUT.read();
unsigned char r;
if (0 != (swSerialConfig & 070))
r = serialIUT.read();
else
r = inBuf[i];
if (expected == -1) { expected = r; }
else {
expected = (expected + 1) % 256;
expected = (expected + 1) % (1UL << (5 + swSerialConfig % 4));
}
if (r != (expected & ((1 << (5 + swSerialConfig % 4)) - 1))) {
if (r != expected) {
++rxErrors;
expected = -1;
}
Expand Down Expand Up @@ -251,7 +259,8 @@ void loop() {
rxParityErrors = 0;
expected = -1;
// resync
delay(static_cast<uint32_t>(1000 * 10 * BLOCKSIZE / IUTBITRATE * 16));
delay(1000UL * 12 * BLOCKSIZE / IUTBITRATE * 16);
serialIUT.flush();
start = micros();
}
}
114 changes: 68 additions & 46 deletions examples/repeater/repeater.ino
Original file line number Diff line number Diff line change
Expand Up @@ -17,110 +17,132 @@
#define TX (1)
#endif

//#define HWLOOPBACK 1
//#define HALFDUPLEX 1
#define HWLOOPBACK 1
#define HALFDUPLEX 1

#ifdef ESP32
constexpr int IUTBITRATE = 57600;
constexpr int IUTBITRATE = 19200;
#else
constexpr int IUTBITRATE = 153600;
constexpr int IUTBITRATE = 19200;
#endif

constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8N1;
#if defined(ESP8266)
constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8E1;
constexpr SerialConfig hwSerialConfig = SERIAL_8E1;
#elif defined(ESP32)
constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8E1;
constexpr uint32_t hwSerialConfig = SERIAL_8E1;
#else
constexpr unsigned swSerialConfig = 3;
#endif
constexpr bool invert = false;

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


unsigned long start;
String bitRateTxt("Effective data rate: ");
int rxCount;
int seqErrors;
int expected;
constexpr int ReportInterval = IUTBITRATE / 8;

#ifdef HWLOOPBACK
#if defined(ESP8266)
#if defined(HWLOOPBACK)
HardwareSerial& repeater(Serial);
SoftwareSerial logger;
#elif defined(ESP32)
HardwareSerial& repeater(Serial2);
#else
SoftwareSerial repeater;
HardwareSerial& logger(Serial);
#endif
#elif defined(ESP32)
#if defined(HWLOOPBACK)
HardwareSerial& repeater(Serial2);
#else
SoftwareSerial repeater;
#endif
HardwareSerial& logger(Serial);
#else
SoftwareSerial repeater(14, 12);
HardwareSerial& logger(Serial);
#endif

void setup() {
#ifdef HWLOOPBACK
#if defined(ESP8266)
repeater.begin(IUTBITRATE);
repeater.setRxBufferSize(2 * BLOCKSIZE);
#if defined(HWLOOPBACK)
repeater.begin(IUTBITRATE, hwSerialConfig, SERIAL_FULL, 1, invert);
repeater.swap();
logger.begin(9600, swSerialConfig, RX, TX);
#elif defined(ESP32)
repeater.begin(IUTBITRATE, SERIAL_8N1, D7, D8);
repeater.setRxBufferSize(2 * BLOCKSIZE);
logger.begin(9600, SWSERIAL_8N1, -1, TX);
#else
repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, invert, 4 * BLOCKSIZE);
#ifdef HALFDUPLEX
repeater.enableIntTx(false);
#endif
logger.begin(9600);
#endif
#else
#if defined(ESP8266)
repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, false, 2 * BLOCKSIZE);
#elif defined(ESP32)
repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, false, 2 * BLOCKSIZE);
#endif
#if defined(HWLOOPBACK)
repeater.begin(IUTBITRATE, hwSerialConfig, D7, D8, invert);
repeater.setRxBufferSize(2 * BLOCKSIZE);
logger.begin(9600);
#else
repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, invert, 4 * BLOCKSIZE);
#ifdef HALFDUPLEX
repeater.enableIntTx(false);
#endif
Serial.begin(9600);
#endif
#else
repeater.begin(IUTBITRATE);
Serial.begin(9600);
#endif

start = micros();
rxCount = 0;
seqErrors = 0;
expected = -1;

logger.println("Repeater example for EspSoftwareSerial");
}

void loop() {
#ifdef HALFDUPLEX
unsigned char block[BLOCKSIZE];
char block[BLOCKSIZE];
#endif
// starting deadline for the first bytes to come in
uint32_t deadlineStart = ESP.getCycleCount();
int inCnt = 0;
while ((ESP.getCycleCount() - deadlineStart) < (1000000 * 10 * BLOCKSIZE) / IUTBITRATE * 2 * ESP.getCpuFreqMHz()) {
int avail = repeater.available();
for (int i = 0; i < avail; ++i)
{
int r = repeater.read();
if (r == -1) { logger.println("read() == -1"); }
if (expected == -1) { expected = r; }
else {
expected = (expected + 1) % 256;
}
if (r != (expected & ((1 << (5 + swSerialConfig % 4)) - 1))) {
++seqErrors;
expected = -1;
}
++rxCount;
while ((ESP.getCycleCount() - deadlineStart) < (1000000UL * 12 * BLOCKSIZE) / IUTBITRATE * 24 * ESP.getCpuFreqMHz()) {
int avail = repeater.available();
for (int i = 0; i < avail; ++i)
{
int r = repeater.read();
if (r == -1) { logger.println("read() == -1"); }
if (expected == -1) { expected = r; }
else {
expected = (expected + 1) % (1UL << (5 + swSerialConfig % 4));
}
if (r != expected) {
++seqErrors;
expected = -1;
}
++rxCount;
#ifdef HALFDUPLEX
block[inCnt] = r;
block[inCnt] = r;
#else
repeater.write(r);
repeater.write(r);
#endif
}
if (++inCnt >= BLOCKSIZE) { break; }
// wait for more outstanding bytes to trickle in
if (avail) deadlineStart = ESP.getCycleCount();
if (++inCnt >= BLOCKSIZE) { break; }
}
if (inCnt >= BLOCKSIZE) { break; }
// wait for more outstanding bytes to trickle in
if (avail) deadlineStart = ESP.getCycleCount();
}

#ifdef HALFDUPLEX
repeater.write(block, inCnt);
#endif

if (inCnt != 0 && inCnt != BLOCKSIZE) {
logger.print("Got "); logger.print(inCnt); logger.println(" bytes during buffer interval");
}

if (rxCount >= ReportInterval) {
auto end = micros();
unsigned long interval = end - start;
Expand Down
5 changes: 2 additions & 3 deletions src/SoftwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,12 @@ size_t SoftwareSerial::read(uint8_t * buffer, size_t size) {
size_t SoftwareSerial::readBytes(uint8_t * buffer, size_t size) {
if (!m_rxValid || !size) { return 0; }
size_t count = 0;
const auto timeout = _timeout * ESP.getCpuFreqMHz() * 1000UL;
const auto start = ESP.getCycleCount();
const auto start = millis();
do {
count += read(&buffer[count], size - count);
if (count >= size) break;
yield();
} while (ESP.getCycleCount() - start < timeout);
} while (millis() - start < _timeout);
return count;
}

Expand Down
4 changes: 2 additions & 2 deletions src/SoftwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,10 @@ class SoftwareSerial : public Stream {
return read(reinterpret_cast<uint8_t*>(buffer), size);
}
/// @returns The number of bytes read into buffer, up to size. Times out if the limit set through
/// Stream::setTimeout() is reached. The maximum permissible timeout at 80MHz CPU freq. is ~26s.
/// Stream::setTimeout() is reached.
size_t readBytes(uint8_t* buffer, size_t size) override;
/// @returns The number of bytes read into buffer, up to size. Times out if the limit set through
/// Stream::setTimeout() is reached. The maximum permissible timeout at 80MHz CPU freq. is ~26s.
/// Stream::setTimeout() is reached.
size_t readBytes(char* buffer, size_t size) override {
return readBytes(reinterpret_cast<uint8_t*>(buffer), size);
}
Expand Down

0 comments on commit 7826def

Please sign in to comment.