Skip to content

Commit 8638957

Browse files
Alex WoldenAlex Wolden
authored andcommitted
Merge remote-tracking branch 'origin/dev' into awolden/t3lora
2 parents d36da0e + 01d84d5 commit 8638957

File tree

19 files changed

+745
-84
lines changed

19 files changed

+745
-84
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#include "UITask.h"
2+
#include <Arduino.h>
3+
#include <helpers/TxtDataHelpers.h>
4+
5+
#define AUTO_OFF_MILLIS 15000 // 15 seconds
6+
7+
// 'meshcore', 128x13px
8+
static const uint8_t meshcore_logo [] PROGMEM = {
9+
0x3c, 0x01, 0xe3, 0xff, 0xc7, 0xff, 0x8f, 0x03, 0x87, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe,
10+
0x3c, 0x03, 0xe3, 0xff, 0xc7, 0xff, 0x8e, 0x03, 0x8f, 0xfe, 0x3f, 0xfe, 0x1f, 0xff, 0x1f, 0xfe,
11+
0x3e, 0x03, 0xc3, 0xff, 0x8f, 0xff, 0x0e, 0x07, 0x8f, 0xfe, 0x7f, 0xfe, 0x1f, 0xff, 0x1f, 0xfc,
12+
0x3e, 0x07, 0xc7, 0x80, 0x0e, 0x00, 0x0e, 0x07, 0x9e, 0x00, 0x78, 0x0e, 0x3c, 0x0f, 0x1c, 0x00,
13+
0x3e, 0x0f, 0xc7, 0x80, 0x1e, 0x00, 0x0e, 0x07, 0x1e, 0x00, 0x70, 0x0e, 0x38, 0x0f, 0x3c, 0x00,
14+
0x7f, 0x0f, 0xc7, 0xfe, 0x1f, 0xfc, 0x1f, 0xff, 0x1c, 0x00, 0x70, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
15+
0x7f, 0x1f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
16+
0x7f, 0x3f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x1e, 0x3f, 0xfe, 0x3f, 0xf0,
17+
0x77, 0x3b, 0x87, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xfc, 0x38, 0x00,
18+
0x77, 0xfb, 0x8f, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xf8, 0x38, 0x00,
19+
0x73, 0xf3, 0x8f, 0xff, 0x0f, 0xff, 0x1c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x78, 0x7f, 0xf8,
20+
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfe, 0x3c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x3c, 0x7f, 0xf8,
21+
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfc, 0x3c, 0x0e, 0x1f, 0xf8, 0xff, 0xf8, 0x70, 0x3c, 0x7f, 0xf8,
22+
};
23+
24+
void UITask::begin(const char* node_name, const char* build_date, uint32_t pin_code) {
25+
_prevBtnState = HIGH;
26+
_auto_off = millis() + AUTO_OFF_MILLIS;
27+
clearMsgPreview();
28+
_node_name = node_name;
29+
_build_date = build_date;
30+
_pin_code = pin_code;
31+
_display->turnOn();
32+
}
33+
34+
void UITask::clearMsgPreview() {
35+
_origin[0] = 0;
36+
_msg[0] = 0;
37+
}
38+
39+
void UITask::showMsgPreview(uint8_t path_len, const char* from_name, const char* text) {
40+
if (path_len == 0xFF) {
41+
sprintf(_origin, "(F) %s", from_name);
42+
} else {
43+
sprintf(_origin, "(%d) %s", (uint32_t) path_len, from_name);
44+
}
45+
StrHelper::strncpy(_msg, text, sizeof(_msg));
46+
47+
if (!_display->isOn()) _display->turnOn();
48+
_auto_off = millis() + AUTO_OFF_MILLIS; // extend the auto-off timer
49+
}
50+
51+
void UITask::renderCurrScreen() {
52+
char tmp[80];
53+
if (_origin[0] && _msg[0]) {
54+
// render message preview
55+
_display->setCursor(0, 0);
56+
_display->setTextSize(1);
57+
_display->print(_node_name);
58+
59+
_display->setCursor(0, 12);
60+
_display->print(_origin);
61+
_display->setCursor(0, 24);
62+
_display->print(_msg);
63+
64+
//_display->setCursor(100, 9); TODO
65+
//_display->setTextSize(2);
66+
//_display->printf("%d", msgs);
67+
} else {
68+
// render 'home' screen
69+
_display->drawXbm(0, 0, meshcore_logo, 128, 13);
70+
_display->setCursor(0, 20);
71+
_display->setTextSize(1);
72+
_display->print(_node_name);
73+
74+
sprintf(tmp, "Build: %s", _build_date);
75+
_display->setCursor(0, 32);
76+
_display->print(tmp);
77+
78+
if (_connected) {
79+
//_display->printf("freq : %03.2f sf %d\n", _prefs.freq, _prefs.sf);
80+
//_display->printf("bw : %03.2f cr %d\n", _prefs.bw, _prefs.cr);
81+
} else {
82+
_display->setTextSize(2);
83+
_display->setCursor(0, 43);
84+
sprintf(tmp, "Pin:%d", _pin_code);
85+
_display->print(tmp);
86+
}
87+
}
88+
}
89+
90+
void UITask::loop() {
91+
if (millis() >= _next_read) {
92+
int btnState = digitalRead(PIN_USER_BTN);
93+
if (btnState != _prevBtnState) {
94+
if (btnState == LOW) { // pressed?
95+
if (_display->isOn()) {
96+
clearMsgPreview();
97+
} else {
98+
_display->turnOn();
99+
}
100+
_auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer
101+
}
102+
_prevBtnState = btnState;
103+
}
104+
_next_read = millis() + 100; // 10 reads per second
105+
}
106+
107+
if (_display->isOn()) {
108+
if (millis() >= _next_refresh) {
109+
_display->startFrame();
110+
renderCurrScreen();
111+
_display->endFrame();
112+
113+
_next_refresh = millis() + 1000; // refresh every second
114+
}
115+
if (millis() > _auto_off) {
116+
_display->turnOff();
117+
}
118+
}
119+
}

examples/companion_radio/UITask.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
3+
#include <helpers/ui/DisplayDriver.h>
4+
5+
class UITask {
6+
DisplayDriver* _display;
7+
unsigned long _next_read, _next_refresh, _auto_off;
8+
int _prevBtnState;
9+
bool _connected;
10+
uint32_t _pin_code;
11+
const char* _node_name;
12+
const char* _build_date;
13+
char _origin[62];
14+
char _msg[80];
15+
16+
void renderCurrScreen();
17+
public:
18+
UITask(DisplayDriver& display) : _display(&display) { _next_read = _next_refresh = 0; _connected = false; }
19+
void begin(const char* node_name, const char* build_date, uint32_t pin_code);
20+
21+
void setHasConnection(bool connected) { _connected = connected; }
22+
void clearMsgPreview();
23+
void showMsgPreview(uint8_t path_len, const char* from_name, const char* text);
24+
void loop();
25+
};

examples/companion_radio/main.cpp

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,15 @@
8888
#error "need to provide a 'board' object"
8989
#endif
9090

91+
#ifdef DISPLAY_CLASS
92+
#include <helpers/ui/SSD1306Display.h>
93+
94+
static DISPLAY_CLASS display;
95+
96+
#include "UITask.h"
97+
static UITask ui_task(display);
98+
#endif
99+
91100
// Believe it or not, this std C function is busted on some platforms!
92101
static uint32_t _atoi(const char* sp) {
93102
uint32_t n = 0;
@@ -182,6 +191,7 @@ struct NodePrefs { // persisted to file
182191
uint8_t tx_power_dbm;
183192
uint8_t unused[3];
184193
float rx_delay_base;
194+
uint32_t ble_pin;
185195
};
186196

187197
class MyMesh : public BaseChatMesh {
@@ -214,6 +224,11 @@ class MyMesh : public BaseChatMesh {
214224
if (!_identity_store->load("_main", self_id)) {
215225
self_id = mesh::LocalIdentity(&trng); // create new random identity
216226
saveMainIdentity(self_id);
227+
228+
#if defined(BLE_PIN_CODE) && defined(DISPLAY_CLASS)
229+
// start with randomly assigned BLE pin
230+
_prefs.ble_pin = trng.nextInt(100000, 999999);
231+
#endif
217232
}
218233
}
219234

@@ -475,6 +490,9 @@ class MyMesh : public BaseChatMesh {
475490
} else {
476491
soundBuzzer();
477492
}
493+
#ifdef DISPLAY_CLASS
494+
ui_task.showMsgPreview(path_len, from.name, text);
495+
#endif
478496
}
479497

480498
void onMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override {
@@ -514,6 +532,9 @@ class MyMesh : public BaseChatMesh {
514532
} else {
515533
soundBuzzer();
516534
}
535+
#ifdef DISPLAY_CLASS
536+
ui_task.showMsgPreview(in_path_len < 0 ? 0xFF : in_path_len, "Public", text);
537+
#endif
517538
}
518539

519540
void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) override {
@@ -600,6 +621,9 @@ class MyMesh : public BaseChatMesh {
600621
_prefs.bw = LORA_BW;
601622
_prefs.cr = LORA_CR;
602623
_prefs.tx_power_dbm = LORA_TX_POWER;
624+
#ifdef BLE_PIN_CODE
625+
_prefs.ble_pin = BLE_PIN_CODE;
626+
#endif
603627
//_prefs.rx_delay_base = 10.0f; enable once new algo fixed
604628
}
605629

@@ -620,7 +644,34 @@ class MyMesh : public BaseChatMesh {
620644
if (_fs->exists("/node_prefs")) {
621645
File file = _fs->open("/node_prefs");
622646
if (file) {
623-
file.read((uint8_t *) &_prefs, sizeof(_prefs));
647+
uint8_t pad[8];
648+
649+
file.read((uint8_t *) &_prefs.airtime_factor, sizeof(float)); // 0
650+
file.read((uint8_t *) _prefs.node_name, sizeof(_prefs.node_name)); // 4
651+
file.read(pad, 4); // 36
652+
file.read((uint8_t *) &_prefs.node_lat, sizeof(_prefs.node_lat)); // 40
653+
file.read((uint8_t *) &_prefs.node_lon, sizeof(_prefs.node_lon)); // 48
654+
file.read((uint8_t *) &_prefs.freq, sizeof(_prefs.freq)); // 56
655+
file.read((uint8_t *) &_prefs.sf, sizeof(_prefs.sf)); // 60
656+
file.read((uint8_t *) &_prefs.cr, sizeof(_prefs.cr)); // 61
657+
file.read((uint8_t *) &_prefs.reserved1, sizeof(_prefs.reserved1)); // 62
658+
file.read((uint8_t *) &_prefs.reserved2, sizeof(_prefs.reserved2)); // 63
659+
file.read((uint8_t *) &_prefs.bw, sizeof(_prefs.bw)); // 64
660+
file.read((uint8_t *) &_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
661+
file.read((uint8_t *) _prefs.unused, sizeof(_prefs.unused)); // 69
662+
file.read((uint8_t *) &_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
663+
file.read(pad, 4); // 76
664+
file.read((uint8_t *) &_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
665+
666+
// sanitise bad pref values
667+
_prefs.rx_delay_base = constrain(_prefs.rx_delay_base, 0, 20.0f);
668+
_prefs.airtime_factor = constrain(_prefs.airtime_factor, 0, 9.0f);
669+
_prefs.freq = constrain(_prefs.freq, 400.0f, 2500.0f);
670+
_prefs.bw = constrain(_prefs.bw, 62.5f, 500.0f);
671+
_prefs.sf = constrain(_prefs.sf, 7, 12);
672+
_prefs.cr = constrain(_prefs.cr, 5, 8);
673+
_prefs.tx_power_dbm = constrain(_prefs.tx_power_dbm, 1, MAX_LORA_TX_POWER);
674+
624675
file.close();
625676
}
626677
}
@@ -639,6 +690,7 @@ class MyMesh : public BaseChatMesh {
639690
}
640691

641692
const char* getNodeName() { return _prefs.node_name; }
693+
uint32_t getBLEPin() { return _prefs.ble_pin; }
642694

643695
void startInterface(BaseSerialInterface& serial) {
644696
_serial = &serial;
@@ -653,7 +705,26 @@ class MyMesh : public BaseChatMesh {
653705
File file = _fs->open("/node_prefs", "w", true);
654706
#endif
655707
if (file) {
656-
file.write((const uint8_t *)&_prefs, sizeof(_prefs));
708+
uint8_t pad[8];
709+
memset(pad, 0, sizeof(pad));
710+
711+
file.write((uint8_t *) &_prefs.airtime_factor, sizeof(float)); // 0
712+
file.write((uint8_t *) _prefs.node_name, sizeof(_prefs.node_name)); // 4
713+
file.write(pad, 4); // 36
714+
file.write((uint8_t *) &_prefs.node_lat, sizeof(_prefs.node_lat)); // 40
715+
file.write((uint8_t *) &_prefs.node_lon, sizeof(_prefs.node_lon)); // 48
716+
file.write((uint8_t *) &_prefs.freq, sizeof(_prefs.freq)); // 56
717+
file.write((uint8_t *) &_prefs.sf, sizeof(_prefs.sf)); // 60
718+
file.write((uint8_t *) &_prefs.cr, sizeof(_prefs.cr)); // 61
719+
file.write((uint8_t *) &_prefs.reserved1, sizeof(_prefs.reserved1)); // 62
720+
file.write((uint8_t *) &_prefs.reserved2, sizeof(_prefs.reserved2)); // 63
721+
file.write((uint8_t *) &_prefs.bw, sizeof(_prefs.bw)); // 64
722+
file.write((uint8_t *) &_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
723+
file.write((uint8_t *) _prefs.unused, sizeof(_prefs.unused)); // 69
724+
file.write((uint8_t *) &_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
725+
file.write(pad, 4); // 76
726+
file.write((uint8_t *) &_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
727+
657728
file.close();
658729
}
659730
}
@@ -1081,6 +1152,11 @@ class MyMesh : public BaseChatMesh {
10811152
} else if (!_serial->isWriteBusy()) {
10821153
checkConnections();
10831154
}
1155+
1156+
#ifdef DISPLAY_CLASS
1157+
ui_task.setHasConnection(_serial->isConnected());
1158+
ui_task.loop();
1159+
#endif
10841160
}
10851161
};
10861162

@@ -1112,7 +1188,7 @@ class MyMesh : public BaseChatMesh {
11121188

11131189
#if defined(NRF52_PLATFORM)
11141190
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
1115-
#elif defined(LILYGO_TLORA) || defined(HELTEC_LORA_V2) // ESP32 with SX1276
1191+
#elif defined(LILYGO_TLORA)
11161192
SPIClass spi;
11171193
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
11181194
#elif defined(P_LORA_SCLK)
@@ -1139,6 +1215,10 @@ void setup() {
11391215
float tcxo = 1.6f;
11401216
#endif
11411217

1218+
#ifdef DISPLAY_CLASS
1219+
display.begin();
1220+
#endif
1221+
11421222
#if defined(NRF52_PLATFORM)
11431223
SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
11441224
SPI.begin();
@@ -1173,7 +1253,7 @@ void setup() {
11731253
#ifdef BLE_PIN_CODE
11741254
char dev_name[32+10];
11751255
sprintf(dev_name, "MeshCore-%s", the_mesh.getNodeName());
1176-
serial_interface.begin(dev_name, BLE_PIN_CODE);
1256+
serial_interface.begin(dev_name, the_mesh.getBLEPin());
11771257
#else
11781258
pinMode(WB_IO2, OUTPUT);
11791259
serial_interface.begin(Serial);
@@ -1189,14 +1269,18 @@ void setup() {
11891269
#elif defined(BLE_PIN_CODE)
11901270
char dev_name[32+10];
11911271
sprintf(dev_name, "MeshCore-%s", the_mesh.getNodeName());
1192-
serial_interface.begin(dev_name, BLE_PIN_CODE);
1272+
serial_interface.begin(dev_name, the_mesh.getBLEPin());
11931273
#else
11941274
serial_interface.begin(Serial);
11951275
#endif
11961276
the_mesh.startInterface(serial_interface);
11971277
#else
11981278
#error "need to define filesystem"
11991279
#endif
1280+
1281+
#ifdef DISPLAY_CLASS
1282+
ui_task.begin(the_mesh.getNodeName(), FIRMWARE_BUILD_DATE, the_mesh.getBLEPin());
1283+
#endif
12001284
}
12011285

12021286
void loop() {

0 commit comments

Comments
 (0)