Skip to content

Commit 04042e3

Browse files
committed
Refactor serial bridge handling
1 parent 97b5190 commit 04042e3

File tree

5 files changed

+147
-93
lines changed

5 files changed

+147
-93
lines changed

examples/simple_repeater/main.cpp

Lines changed: 87 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -80,25 +80,6 @@
8080

8181
#ifdef BRIDGE_OVER_SERIAL
8282
#define SERIAL_PKT_MAGIC 0xcafe
83-
84-
struct SerialPacket {
85-
uint16_t magic, len, crc;
86-
uint8_t payload[MAX_TRANS_UNIT];
87-
SerialPacket() : magic(SERIAL_PKT_MAGIC), len(0), crc(0) {}
88-
};
89-
90-
// Fletcher-16
91-
// https://en.wikipedia.org/wiki/Fletcher%27s_checksum
92-
static uint16_t fletcher16(const uint8_t *bytes, const size_t len) {
93-
uint8_t sum1 = 0, sum2 = 0;
94-
95-
for (size_t i = 0; i < len; i++) {
96-
sum1 = (sum1 + bytes[i]) % 255;
97-
sum2 = (sum2 + sum1) % 255;
98-
}
99-
100-
return (sum2 << 8) | sum1;
101-
};
10283
#endif
10384

10485
#define REQ_TYPE_GET_STATUS 0x01 // same as _GET_STATS
@@ -267,6 +248,89 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
267248
#endif
268249
}
269250

251+
#ifdef BRIDGE_OVER_SERIAL
252+
struct SerialPacket {
253+
uint16_t magic, len, crc;
254+
uint8_t payload[MAX_TRANS_UNIT];
255+
SerialPacket() : magic(SERIAL_PKT_MAGIC), len(0), crc(0) {}
256+
};
257+
258+
// Fletcher-16
259+
// https://en.wikipedia.org/wiki/Fletcher%27s_checksum
260+
inline static uint16_t fletcher16(const uint8_t *bytes, const size_t len) {
261+
uint8_t sum1 = 0, sum2 = 0;
262+
263+
for (size_t i = 0; i < len; i++) {
264+
sum1 = (sum1 + bytes[i]) % 255;
265+
sum2 = (sum2 + sum1) % 255;
266+
}
267+
268+
return (sum2 << 8) | sum1;
269+
};
270+
271+
inline void serialBridgeSendPkt(const mesh::Packet *pkt) {
272+
SerialPacket spkt;
273+
spkt.len = pkt->writeTo(spkt.payload);
274+
spkt.crc = fletcher16(spkt.payload, spkt.len);
275+
BRIDGE_OVER_SERIAL.write((uint8_t *)&spkt, sizeof(SerialPacket));
276+
277+
#if MESH_PACKET_LOGGING
278+
Serial.printf("%s: BRIDGE: TX, len=%d crc=0x%04x\n", getLogDateTime(), spkt.len, spkt.crc);
279+
#endif
280+
}
281+
282+
inline void serialBridgeReceivePkt() {
283+
static constexpr uint16_t size = sizeof(SerialPacket) + 1;
284+
static uint8_t buffer[size];
285+
static uint16_t tail = 0;
286+
287+
while (BRIDGE_OVER_SERIAL.available()) {
288+
buffer[tail] = (uint8_t)BRIDGE_OVER_SERIAL.read();
289+
MESH_DEBUG_PRINT("%02x ", buffer[tail]);
290+
tail = (tail + 1) % size;
291+
292+
// Check for complete packet by looking back to where the magic number should be
293+
const uint16_t head = (tail - sizeof(SerialPacket) + size) % size;
294+
if ((buffer[head] | (buffer[(head + 1) % size] << 8)) != SERIAL_PKT_MAGIC) {
295+
return;
296+
}
297+
298+
uint8_t bytes[MAX_TRANS_UNIT];
299+
const uint16_t len = buffer[(head + 2) % size] | (buffer[(head + 3) % size] << 8);
300+
301+
if (len == 0 || len > sizeof(bytes)) {
302+
MESH_DEBUG_PRINTLN("%s: BRIDGE: RX, invalid packet len", getLogDateTime());
303+
return;
304+
}
305+
306+
for (size_t i = 0; i < len; i++) {
307+
bytes[i] = buffer[(head + 6 + i) % size];
308+
}
309+
310+
const uint16_t crc = buffer[(head + 4) % size] | (buffer[(head + 5) % size] << 8);
311+
const uint16_t f16 = fletcher16(bytes, len);
312+
313+
#if MESH_PACKET_LOGGING
314+
Serial.printf("%s: BRIDGE: RX, len=%d crc=0x%04x\n", getLogDateTime(), len, crc);
315+
#endif
316+
317+
if ((f16 != crc)) {
318+
MESH_DEBUG_PRINTLN("%s: BRIDGE: RX, invalid packet checksum", getLogDateTime());
319+
return;
320+
}
321+
322+
mesh::Packet *pkt = _mgr->allocNew();
323+
if (pkt == NULL) {
324+
MESH_DEBUG_PRINTLN("%s: BRIDGE: RX, no unused packets available", getLogDateTime());
325+
return;
326+
}
327+
328+
pkt->readFrom(bytes, len);
329+
_mgr->queueInbound(pkt, futureMillis(0));
330+
}
331+
}
332+
#endif
333+
270334
protected:
271335
float getAirtimeBudgetFactor() const override {
272336
return _prefs.airtime_factor;
@@ -316,21 +380,10 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
316380
}
317381
void logTx(mesh::Packet* pkt, int len) override {
318382
#ifdef BRIDGE_OVER_SERIAL
319-
SerialPacket serialpkt;
320-
size_t seriallen = pkt->writeTo(serialpkt.payload);
321-
322-
if (seriallen - 1 < MAX_TRANS_UNIT - 1) {
323-
serialpkt.len = seriallen;
324-
serialpkt.crc = fletcher16(serialpkt.payload, serialpkt.len);
325-
BRIDGE_OVER_SERIAL.write((uint8_t *)&serialpkt, sizeof(SerialPacket));
326-
327-
#if MESH_PACKET_LOGGING
328-
Serial.print(getLogDateTime());
329-
Serial.printf(": BRIDGE: Write to serial len=%d crc=0x%04x\n", serialpkt.len, serialpkt.crc);
330-
#endif
383+
if (!pkt->isMarkedDoNotRetransmit()) {
384+
serialBridgeSendPkt(pkt);
331385
}
332386
#endif
333-
334387
if (_logging) {
335388
File f = openAppend(PACKET_LOG_FILE);
336389
if (f) {
@@ -747,53 +800,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
747800

748801
void loop() {
749802
#ifdef BRIDGE_OVER_SERIAL
750-
static constexpr uint16_t size = sizeof(SerialPacket) + 1;
751-
static uint8_t buffer[size];
752-
static uint16_t tail = 0;
753-
754-
while (BRIDGE_OVER_SERIAL.available()) {
755-
buffer[tail] = (uint8_t)BRIDGE_OVER_SERIAL.read();
756-
MESH_DEBUG_PRINT("%02x ", buffer[tail]);
757-
tail = (tail + 1) % size;
758-
759-
// Check for complete packet by looking back to where the magic number should be
760-
uint16_t head = (tail - sizeof(SerialPacket) + size) % size;
761-
const uint16_t magic = buffer[head] | (buffer[(head + 1) % size] << 8);
762-
763-
if (magic == SERIAL_PKT_MAGIC) {
764-
uint8_t bytes[MAX_TRANS_UNIT];
765-
const uint16_t len = buffer[(head + 2) % size] | (buffer[(head + 3) % size] << 8);
766-
const uint16_t crc = buffer[(head + 4) % size] | (buffer[(head + 5) % size] << 8);
767-
768-
if (len - 1 < MAX_TRANS_UNIT - 1) {
769-
for (size_t i = 0; i < len; i++) {
770-
bytes[i] = buffer[(head + 6 + i) % size];
771-
}
772-
773-
uint16_t f16 = fletcher16(bytes, len);
774-
775-
#if MESH_PACKET_LOGGING
776-
Serial.print(getLogDateTime());
777-
Serial.printf(": BRIDGE: Read from serial len=%d crc=0x%04x valid=%s\n", len, crc,
778-
(f16 == crc) ? "true" : "false");
779-
#endif
780-
781-
if (f16 == crc) {
782-
mesh::Packet *pkt = _mgr->allocNew();
783-
784-
if (pkt == NULL) {
785-
#if MESH_PACKET_LOGGING
786-
Serial.print(getLogDateTime());
787-
Serial.printf(": BRIDGE: Unable to allocate new Packet *pkt\n");
788-
#endif
789-
} else {
790-
pkt->readFrom(bytes, len);
791-
_mgr->queueInbound(pkt, millis());
792-
}
793-
}
794-
}
795-
}
796-
}
803+
serialBridgeReceivePkt();
797804
#endif
798805

799806
mesh::Mesh::loop();
@@ -829,6 +836,7 @@ static char command[80];
829836

830837
void setup() {
831838
Serial.begin(115200);
839+
delay(1000);
832840

833841
#ifdef BRIDGE_OVER_SERIAL
834842
#if defined(ESP32)
@@ -842,13 +850,9 @@ void setup() {
842850
#else
843851
#error SerialBridge was not tested on the current platform
844852
#endif
845-
846853
BRIDGE_OVER_SERIAL.begin(115200);
847-
MESH_DEBUG_PRINTLN("Bridge over serial: enabled");
848854
#endif
849855

850-
delay(1000);
851-
852856
board.begin();
853857

854858
#ifdef DISPLAY_CLASS

platformio.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ build_flags = -w -DNDEBUG -DRADIOLIB_STATIC_ONLY=1 -DRADIOLIB_GODMODE=1
3232
build_src_filter =
3333
+<*.cpp>
3434
+<helpers/*.cpp>
35-
+<bridge/**/*.cpp>
3635

3736
; ----------------- ESP32 ---------------------
3837

variants/heltec_v3/platformio.ini

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ build_flags =
4949
-D ADVERT_LON=0.0
5050
-D ADMIN_PASSWORD='"password"'
5151
-D MAX_NEIGHBOURS=8
52-
; -D BRIDGE_OVER_SERIAL=Serial2
53-
; -D BRIDGE_OVER_SERIAL_RX=5
54-
; -D BRIDGE_OVER_SERIAL_TX=6
5552
; -D MESH_PACKET_LOGGING=1
5653
; -D MESH_DEBUG=1
5754
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
@@ -61,6 +58,28 @@ lib_deps =
6158
${Heltec_lora32_v3.lib_deps}
6259
${esp32_ota.lib_deps}
6360

61+
[env:Heltec_v3_Bridge]
62+
extends = Heltec_lora32_v3
63+
build_flags =
64+
${Heltec_lora32_v3.build_flags}
65+
-D DISPLAY_CLASS=SSD1306Display
66+
-D ADVERT_NAME='"Heltec Bridge"'
67+
-D ADVERT_LAT=0.0
68+
-D ADVERT_LON=0.0
69+
-D ADMIN_PASSWORD='"password"'
70+
-D MAX_NEIGHBOURS=8
71+
-D BRIDGE_OVER_SERIAL=Serial2
72+
-D BRIDGE_OVER_SERIAL_RX=5
73+
-D BRIDGE_OVER_SERIAL_TX=6
74+
-D MESH_PACKET_LOGGING=1
75+
; -D MESH_DEBUG=1
76+
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
77+
+<helpers/ui/SSD1306Display.cpp>
78+
+<../examples/simple_repeater>
79+
lib_deps =
80+
${Heltec_lora32_v3.lib_deps}
81+
${esp32_ota.lib_deps}
82+
6483
[env:Heltec_v3_room_server]
6584
extends = Heltec_lora32_v3
6685
build_flags =

variants/lilygo_tlora_v2_1/platformio.ini

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,35 @@ build_flags =
5757
-D ADVERT_LON=0.0
5858
-D ADMIN_PASSWORD='"password"'
5959
-D MAX_NEIGHBOURS=8
60-
; -D BRIDGE_OVER_SERIAL=Serial2
61-
; -D BRIDGE_OVER_SERIAL_RX=34
62-
; -D BRIDGE_OVER_SERIAL_TX=25
6360
; -D MESH_PACKET_LOGGING=1
6461
; -D MESH_DEBUG=1
6562
; -D CORE_DEBUG_LEVEL=3
6663
lib_deps =
6764
${LilyGo_TLora_V2_1_1_6.lib_deps}
6865
${esp32_ota.lib_deps}
6966

67+
[env:LilyGo_TLora_V2_1_1_6_Bridge]
68+
extends = LilyGo_TLora_V2_1_1_6
69+
build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter}
70+
+<helpers/ui/SSD1306Display.cpp>
71+
+<../examples/simple_repeater>
72+
build_flags =
73+
${LilyGo_TLora_V2_1_1_6.build_flags}
74+
-D ADVERT_NAME='"TLora-V2.1-1.6 Bridge"'
75+
-D ADVERT_LAT=0.0
76+
-D ADVERT_LON=0.0
77+
-D ADMIN_PASSWORD='"password"'
78+
-D MAX_NEIGHBOURS=8
79+
-D BRIDGE_OVER_SERIAL=Serial2
80+
-D BRIDGE_OVER_SERIAL_RX=34
81+
-D BRIDGE_OVER_SERIAL_TX=25
82+
-D MESH_PACKET_LOGGING=1
83+
; -D MESH_DEBUG=1
84+
; -D CORE_DEBUG_LEVEL=3
85+
lib_deps =
86+
${LilyGo_TLora_V2_1_1_6.lib_deps}
87+
${esp32_ota.lib_deps}
88+
7089
[env:LilyGo_TLora_V2_1_1_6_terminal_chat]
7190
extends = LilyGo_TLora_V2_1_1_6
7291
build_flags =

variants/waveshare_rp2040_lora/platformio.ini

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,27 @@ build_flags = ${waveshare_rp2040_lora.build_flags}
3535
-D ADVERT_LON=0.0
3636
-D ADMIN_PASSWORD='"password"'
3737
-D MAX_NEIGHBOURS=8
38-
; -D BRIDGE_OVER_SERIAL=Serial2
39-
; -D BRIDGE_OVER_SERIAL_RX=9
40-
; -D BRIDGE_OVER_SERIAL_TX=8
4138
; -D MESH_PACKET_LOGGING=1
4239
; -D MESH_DEBUG=1
4340
build_src_filter = ${waveshare_rp2040_lora.build_src_filter}
4441
+<../examples/simple_repeater>
4542

43+
[env:waveshare_rp2040_lora_Bridge]
44+
extends = waveshare_rp2040_lora
45+
build_flags = ${waveshare_rp2040_lora.build_flags}
46+
-D ADVERT_NAME='"RP2040-LoRa Bridge"'
47+
-D ADVERT_LAT=0.0
48+
-D ADVERT_LON=0.0
49+
-D ADMIN_PASSWORD='"password"'
50+
-D MAX_NEIGHBOURS=8
51+
-D BRIDGE_OVER_SERIAL=Serial2
52+
-D BRIDGE_OVER_SERIAL_RX=9
53+
-D BRIDGE_OVER_SERIAL_TX=8
54+
-D MESH_PACKET_LOGGING=1
55+
; -D MESH_DEBUG=1
56+
build_src_filter = ${waveshare_rp2040_lora.build_src_filter}
57+
+<../examples/simple_repeater>
58+
4659
[env:waveshare_rp2040_lora_room_server]
4760
extends = waveshare_rp2040_lora
4861
build_flags = ${waveshare_rp2040_lora.build_flags}

0 commit comments

Comments
 (0)