|
16 | 16 | // Hardware Serial2 defaults to D4 (rx), D3 (tx).
|
17 | 17 | // For local hardware loopback, connect D5 (rx) to D3 (tx), D6 (tx) to D4 (rx).
|
18 | 18 |
|
19 |
| -#if !defined(D5) |
| 19 | +#if defined(ESP8266) && !defined(D5) |
20 | 20 | #define D5 (14)
|
21 | 21 | #define D6 (12)
|
22 | 22 | #define D7 (13)
|
23 | 23 | #define D8 (15)
|
24 | 24 | #endif
|
25 | 25 |
|
26 | 26 | // Pick only one of HWLOOPBACK OR HWSENDNSINK
|
27 |
| -//#define HWLOOPBACK 1 |
| 27 | +#define HWLOOPBACK 1 |
28 | 28 | //#define HWSENDNSINK 1
|
29 |
| -//#define HALFDUPLEX 1 |
| 29 | +#define HALFDUPLEX 1 |
30 | 30 |
|
31 | 31 | #ifdef ESP32
|
32 |
| -constexpr int IUTBITRATE = 19200; |
| 32 | +constexpr int IUTBITRATE = 115200; |
33 | 33 | #else
|
34 |
| -constexpr int IUTBITRATE = 19200; |
| 34 | +constexpr int IUTBITRATE = 115200; |
35 | 35 | #endif
|
36 | 36 |
|
37 | 37 | #if defined(ESP8266) || defined(ESP32)
|
@@ -81,159 +81,151 @@ HardwareSerial& logger(Serial);
|
81 | 81 | void setup() {
|
82 | 82 | #if defined(ESP8266)
|
83 | 83 | #if defined(HWLOOPBACK) || defined(HWSENDNSINK)
|
84 |
| - Serial.begin(IUTBITRATE); |
85 |
| - Serial.swap(); |
86 |
| - Serial.setRxBufferSize(4 * BLOCKSIZE); |
87 |
| - logger.begin(9600, RX, TX); |
| 84 | + Serial.begin(IUTBITRATE); |
| 85 | + Serial.swap(); |
| 86 | + Serial.setRxBufferSize(2 * BLOCKSIZE); |
| 87 | + logger.begin(9600, -1, TX); |
88 | 88 | #else
|
89 |
| - Serial.begin(9600); |
| 89 | + Serial.begin(9600); |
90 | 90 | #endif
|
91 | 91 | #elif defined(ESP32)
|
92 | 92 | #if defined(HWLOOPBACK)
|
93 |
| - Serial2.begin(IUTBITRATE); |
94 |
| - Serial2.setRxBufferSize(4 * BLOCKSIZE); |
95 |
| - logger.begin(9600); |
| 93 | + Serial2.begin(IUTBITRATE); |
| 94 | + Serial2.setRxBufferSize(2 * BLOCKSIZE); |
| 95 | + logger.begin(9600); |
96 | 96 | #elif defined(HWSENDNSINK)
|
97 |
| - serialIUT.begin(IUTBITRATE, SERIAL_8N1, D5, D6); |
98 |
| - serialIUT.setRxBufferSize(4 * BLOCKSIZE); |
99 |
| - logger.begin(9600); |
| 97 | + serialIUT.begin(IUTBITRATE, SERIAL_8N1, D5, D6); |
| 98 | + serialIUT.setRxBufferSize(2 * BLOCKSIZE); |
| 99 | + logger.begin(9600); |
100 | 100 | #else
|
101 |
| -Serial.begin(9600); |
| 101 | + Serial.begin(9600); |
102 | 102 | #endif
|
103 | 103 | #else
|
104 |
| - Serial.begin(9600); |
| 104 | + Serial.begin(9600); |
105 | 105 | #endif
|
106 | 106 |
|
107 | 107 | #if !defined(HWSENDNSINK)
|
108 | 108 | #if defined(ESP8266)
|
109 |
| - serialIUT.begin(IUTBITRATE, D5, D6, swSerialConfig, false, 4 * BLOCKSIZE); |
| 109 | + serialIUT.begin(IUTBITRATE, D5, D6, swSerialConfig, false, 4 * BLOCKSIZE); |
110 | 110 | #ifdef HALFDUPLEX
|
111 |
| - serialIUT.enableIntTx(false); |
| 111 | + serialIUT.enableIntTx(false); |
112 | 112 | #endif
|
113 | 113 | #elif defined(ESP32)
|
114 |
| - serialIUT.begin(IUTBITRATE, D5, D6, swSerialConfig, false, 4 * BLOCKSIZE); |
| 114 | + serialIUT.begin(IUTBITRATE, D5, D6, swSerialConfig, false, 2 * BLOCKSIZE); |
115 | 115 | #ifdef HALFDUPLEX
|
116 |
| - serialIUT.enableIntTx(false); |
| 116 | + serialIUT.enableIntTx(false); |
117 | 117 | #endif
|
118 | 118 | #else
|
119 |
| - serialIUT.begin(IUTBITRATE); |
| 119 | + serialIUT.begin(IUTBITRATE); |
120 | 120 | #endif
|
121 | 121 | #endif
|
122 | 122 |
|
123 |
| - start = micros(); |
124 |
| - txCount = 0; |
125 |
| - rxCount = 0; |
126 |
| - rxErrors = 0; |
| 123 | + start = micros(); |
| 124 | + txCount = 0; |
| 125 | + rxCount = 0; |
| 126 | + rxErrors = 0; |
127 | 127 |
|
128 |
| - logger.println("Loopback example for EspSoftwareSerial"); |
| 128 | + logger.println("Loopback example for EspSoftwareSerial"); |
129 | 129 | }
|
130 | 130 |
|
131 | 131 | unsigned char c = 0;
|
132 | 132 |
|
133 | 133 | void loop() {
|
134 | 134 | #ifdef HALFDUPLEX
|
135 |
| - unsigned char block[BLOCKSIZE]; |
| 135 | + unsigned char block[2 * BLOCKSIZE]; |
136 | 136 | #endif
|
137 |
| - unsigned char inBuf[BLOCKSIZE]; |
138 |
| - for (int i = 0; i < BLOCKSIZE; ++i) { |
| 137 | + unsigned char inBuf[2 * BLOCKSIZE]; |
| 138 | + for (int i = 0; i < BLOCKSIZE; ++i) { |
139 | 139 | #ifndef HALFDUPLEX
|
140 |
| - serialIUT.write(c); |
| 140 | + serialIUT.write(c); |
141 | 141 | #ifdef HWLOOPBACK
|
142 |
| - int avail = hwLoopback.available(); |
143 |
| - while ((0 == (i % 8)) && avail > 0) { |
144 |
| - int inCnt = hwLoopback.readBytes(inBuf, min(avail, min(BLOCKSIZE, hwLoopback.availableForWrite()))); |
145 |
| - hwLoopback.write(inBuf, inCnt); |
146 |
| - avail -= inCnt; |
147 |
| - } |
| 142 | + int avail = hwLoopback.available(); |
| 143 | + while ((0 == (i % 8)) && avail > 0) { |
| 144 | + int inCnt = hwLoopback.readBytes(inBuf, min(avail, min(BLOCKSIZE, hwLoopback.availableForWrite()))); |
| 145 | + hwLoopback.write(inBuf, inCnt); |
| 146 | + avail -= inCnt; |
| 147 | + } |
148 | 148 | #endif
|
149 | 149 | #else
|
150 |
| - block[i] = c; |
| 150 | + block[i] = c; |
151 | 151 | #endif
|
152 |
| - c = (c + 1) % 256; |
153 |
| - ++txCount; |
154 |
| - } |
| 152 | + c = (c + 1) % 256; |
| 153 | + ++txCount; |
| 154 | + } |
155 | 155 | #ifdef HALFDUPLEX
|
156 |
| - serialIUT.write(block, BLOCKSIZE); |
| 156 | + serialIUT.write(block, BLOCKSIZE); |
157 | 157 | #endif
|
158 | 158 | #ifdef HWSENDNSINK
|
159 | 159 | #if defined(ESP8266)
|
160 |
| - if (Serial.hasOverrun()) { logger.println("Serial::overrun"); } |
| 160 | + if (Serial.hasOverrun()) { logger.println("Serial::overrun"); } |
161 | 161 | #endif
|
162 | 162 | #else
|
163 |
| - if (serialIUT.overflow()) { logger.println("SoftwareSerial::overflow"); } |
| 163 | + if (serialIUT.overflow()) { logger.println("SoftwareSerial::overflow"); } |
164 | 164 | #endif
|
165 | 165 |
|
166 |
| - uint32_t deadline; |
167 |
| - int inCnt; |
| 166 | + int inCnt; |
| 167 | + uint32_t deadlineStart; |
168 | 168 |
|
169 | 169 | #ifdef HWLOOPBACK
|
170 |
| - // starting deadline for the first bytes to become readable |
171 |
| - deadline = micros() + static_cast<uint32_t>(1000000 * 10 * BLOCKSIZE / IUTBITRATE * 8); |
172 |
| - inCnt = 0; |
173 |
| - while (static_cast<int32_t>(deadline - micros()) > 0) { |
174 |
| - int avail = hwLoopback.available(); |
175 |
| - if (0 >= avail) { |
176 |
| - delay(1); |
177 |
| - continue; |
178 |
| - } |
179 |
| - inCnt += hwLoopback.readBytes(&inBuf[inCnt], min(avail, min(BLOCKSIZE - inCnt, hwLoopback.availableForWrite()))); |
180 |
| - if (inCnt >= BLOCKSIZE) { break; } |
181 |
| - // wait for more outstanding bytes to trickle in |
182 |
| - deadline = micros() + static_cast<uint32_t>(1000000 * 10 * BLOCKSIZE / IUTBITRATE * 8); |
183 |
| - } |
184 |
| - hwLoopback.write(inBuf, inCnt); |
185 |
| -#endif |
186 |
| - |
187 |
| - // starting deadline for the first bytes to come in |
188 |
| - deadline = micros() + static_cast<uint32_t>(1000000 * 10 * BLOCKSIZE / IUTBITRATE * 16); |
189 |
| - inCnt = 0; |
190 |
| - while (static_cast<int32_t>(deadline - micros()) > 0) { |
191 |
| - int avail; |
192 |
| - if (0 >= (avail = serialIUT.available())) { |
193 |
| - delay(1); |
194 |
| - continue; |
195 |
| - } |
196 |
| - avail = serialIUT.readBytes(inBuf, BLOCKSIZE); |
197 |
| - for (int i = 0; i < avail; ++i) { |
198 |
| - unsigned char r = inBuf[i]; |
199 |
| - if (expected == -1) { expected = r; } |
200 |
| - else { |
201 |
| - expected = (expected + 1) % 256; |
202 |
| - } |
203 |
| - if (r != (expected & ((1 << (5 + swSerialConfig % 4)) - 1))) { |
204 |
| - ++rxErrors; |
205 |
| - expected = -1; |
206 |
| - } |
207 |
| - ++rxCount; |
208 |
| - ++inCnt; |
209 |
| - } |
210 |
| - if (inCnt >= BLOCKSIZE) { break; } |
211 |
| - // wait for more outstanding bytes to trickle in |
212 |
| - deadline = micros() + static_cast<uint32_t>(1000000 * 10 * BLOCKSIZE / IUTBITRATE * 16); |
213 |
| - } |
214 |
| - |
215 |
| -#ifdef HALFDUPLEX |
216 |
| - if (inCnt != BLOCKSIZE) { |
217 |
| - logger.print("Got "); logger.print(inCnt); logger.println(" bytes during block loopback interval"); |
218 |
| - } |
219 |
| -#endif |
220 |
| - |
221 |
| - if (txCount >= ReportInterval) { |
222 |
| - logger.println(String("tx/rx: ") + txCount + "/" + rxCount); |
223 |
| - const auto end = micros(); |
224 |
| - const unsigned long interval = end - start; |
225 |
| - const long txCps = txCount * (1000000.0 / interval); |
226 |
| - const long rxCps = rxCount * (1000000.0 / interval); |
227 |
| - const long errorCps = rxErrors * (1000000.0 / interval); |
228 |
| - logger.println(effTxTxt + 10 * txCps + "bps, " |
229 |
| - + effRxTxt + 10 * rxCps + "bps, " |
230 |
| - + errorCps + "cps errors (" + 100.0 * rxErrors / rxCount + "%)"); |
231 |
| - txCount = 0; |
232 |
| - rxCount = 0; |
233 |
| - rxErrors = 0; |
234 |
| - expected = -1; |
235 |
| - // resync |
236 |
| - delay(static_cast<uint32_t>(1000 * 10 * BLOCKSIZE / IUTBITRATE * 48)); |
237 |
| - start = micros(); |
238 |
| - } |
| 170 | + // starting deadline for the first bytes to become readable |
| 171 | + deadlineStart = ESP.getCycleCount(); |
| 172 | + inCnt = 0; |
| 173 | + while ((ESP.getCycleCount() - deadlineStart) < (1000000 * 10 * BLOCKSIZE) / IUTBITRATE * 8 * ESP.getCpuFreqMHz()) { |
| 174 | + int avail = hwLoopback.available(); |
| 175 | + if (0 >= avail) { |
| 176 | + delay(1); |
| 177 | + continue; |
| 178 | + } |
| 179 | + inCnt += hwLoopback.readBytes(&inBuf[inCnt], min(avail, min(BLOCKSIZE - inCnt, hwLoopback.availableForWrite()))); |
| 180 | + if (inCnt >= BLOCKSIZE) { break; } |
| 181 | + // wait for more outstanding bytes to trickle in |
| 182 | + deadlineStart = ESP.getCycleCount(); |
| 183 | + } |
| 184 | + hwLoopback.write(inBuf, inCnt); |
| 185 | +#endif |
| 186 | + |
| 187 | + // starting deadline for the first bytes to come in |
| 188 | + deadlineStart = ESP.getCycleCount(); |
| 189 | + inCnt = 0; |
| 190 | + while ((ESP.getCycleCount() - deadlineStart) < (1000000 * 10 * BLOCKSIZE) / IUTBITRATE * 2 * ESP.getCpuFreqMHz()) { |
| 191 | + int avail; |
| 192 | + if (0 >= (avail = serialIUT.available())) { |
| 193 | + continue; |
| 194 | + } |
| 195 | + avail = serialIUT.readBytes(inBuf, min(avail, 2 * BLOCKSIZE)); |
| 196 | + for (int i = 0; i < avail; ++i) { |
| 197 | + unsigned char r = inBuf[i]; |
| 198 | + if (expected == -1) { expected = r; } |
| 199 | + else { |
| 200 | + expected = (expected + 1) % 256; |
| 201 | + } |
| 202 | + if (r != (expected & ((1 << (5 + swSerialConfig % 4)) - 1))) { |
| 203 | + ++rxErrors; |
| 204 | + expected = -1; |
| 205 | + } |
| 206 | + ++rxCount; |
| 207 | + ++inCnt; |
| 208 | + } |
| 209 | + if (inCnt >= BLOCKSIZE) { break; } |
| 210 | + // wait for more outstanding bytes to trickle in |
| 211 | + deadlineStart = ESP.getCycleCount(); |
| 212 | + } |
| 213 | + |
| 214 | + const uint32_t interval = micros() - start; |
| 215 | + if (txCount >= ReportInterval && interval) { |
| 216 | + logger.println(String("tx/rx: ") + txCount + "/" + rxCount); |
| 217 | + const long txCps = txCount * (1000000.0 / interval); |
| 218 | + const long rxCps = rxCount * (1000000.0 / interval); |
| 219 | + const long errorCps = rxErrors * (1000000.0 / interval); |
| 220 | + logger.println(effTxTxt + 10 * txCps + "bps, " |
| 221 | + + effRxTxt + 10 * rxCps + "bps, " |
| 222 | + + errorCps + "cps errors (" + 100.0 * rxErrors / (!rxErrors ? 1 : rxCount) + "%)"); |
| 223 | + txCount = 0; |
| 224 | + rxCount = 0; |
| 225 | + rxErrors = 0; |
| 226 | + expected = -1; |
| 227 | + // resync |
| 228 | + delay(static_cast<uint32_t>(1000 * 10 * BLOCKSIZE / IUTBITRATE * 16)); |
| 229 | + start = micros(); |
| 230 | + } |
239 | 231 | }
|
0 commit comments