Skip to content

Commit c2ae343

Browse files
author
Scott Powell
committed
* basic UITask added to repeater and room server (only HeltecV3 targets enable so far)
1 parent 372c228 commit c2ae343

File tree

7 files changed

+242
-2
lines changed

7 files changed

+242
-2
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include "UITask.h"
2+
#include <Arduino.h>
3+
4+
#define AUTO_OFF_MILLIS 20000 // 20 seconds
5+
6+
// 'meshcore', 128x13px
7+
static const uint8_t meshcore_logo [] PROGMEM = {
8+
0x3c, 0x01, 0xe3, 0xff, 0xc7, 0xff, 0x8f, 0x03, 0x87, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe,
9+
0x3c, 0x03, 0xe3, 0xff, 0xc7, 0xff, 0x8e, 0x03, 0x8f, 0xfe, 0x3f, 0xfe, 0x1f, 0xff, 0x1f, 0xfe,
10+
0x3e, 0x03, 0xc3, 0xff, 0x8f, 0xff, 0x0e, 0x07, 0x8f, 0xfe, 0x7f, 0xfe, 0x1f, 0xff, 0x1f, 0xfc,
11+
0x3e, 0x07, 0xc7, 0x80, 0x0e, 0x00, 0x0e, 0x07, 0x9e, 0x00, 0x78, 0x0e, 0x3c, 0x0f, 0x1c, 0x00,
12+
0x3e, 0x0f, 0xc7, 0x80, 0x1e, 0x00, 0x0e, 0x07, 0x1e, 0x00, 0x70, 0x0e, 0x38, 0x0f, 0x3c, 0x00,
13+
0x7f, 0x0f, 0xc7, 0xfe, 0x1f, 0xfc, 0x1f, 0xff, 0x1c, 0x00, 0x70, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
14+
0x7f, 0x1f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
15+
0x7f, 0x3f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x1e, 0x3f, 0xfe, 0x3f, 0xf0,
16+
0x77, 0x3b, 0x87, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xfc, 0x38, 0x00,
17+
0x77, 0xfb, 0x8f, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xf8, 0x38, 0x00,
18+
0x73, 0xf3, 0x8f, 0xff, 0x0f, 0xff, 0x1c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x78, 0x7f, 0xf8,
19+
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfe, 0x3c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x3c, 0x7f, 0xf8,
20+
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfc, 0x3c, 0x0e, 0x1f, 0xf8, 0xff, 0xf8, 0x70, 0x3c, 0x7f, 0xf8,
21+
};
22+
23+
void UITask::begin(const char* node_name, const char* build_date) {
24+
_prevBtnState = HIGH;
25+
_auto_off = millis() + AUTO_OFF_MILLIS;
26+
_node_name = node_name;
27+
_build_date = build_date;
28+
_display->turnOn();
29+
}
30+
31+
void UITask::renderCurrScreen() {
32+
char tmp[80];
33+
// render 'home' screen
34+
_display->drawXbm(0, 0, meshcore_logo, 128, 13);
35+
_display->setCursor(0, 20);
36+
_display->setTextSize(1);
37+
_display->print(_node_name);
38+
39+
sprintf(tmp, "Build: %s", _build_date);
40+
_display->setCursor(0, 32);
41+
_display->print(tmp);
42+
_display->setCursor(0, 43);
43+
_display->print("< Repeater >");
44+
//_display->printf("freq : %03.2f sf %d\n", _prefs.freq, _prefs.sf);
45+
//_display->printf("bw : %03.2f cr %d\n", _prefs.bw, _prefs.cr);
46+
}
47+
48+
void UITask::loop() {
49+
#ifdef PIN_USER_BTN
50+
if (millis() >= _next_read) {
51+
int btnState = digitalRead(PIN_USER_BTN);
52+
if (btnState != _prevBtnState) {
53+
if (btnState == LOW) { // pressed?
54+
if (_display->isOn()) {
55+
// TODO: any action ?
56+
} else {
57+
_display->turnOn();
58+
}
59+
_auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer
60+
}
61+
_prevBtnState = btnState;
62+
}
63+
_next_read = millis() + 200; // 5 reads per second
64+
}
65+
#endif
66+
67+
if (_display->isOn()) {
68+
if (millis() >= _next_refresh) {
69+
_display->startFrame();
70+
renderCurrScreen();
71+
_display->endFrame();
72+
73+
_next_refresh = millis() + 1000; // refresh every second
74+
}
75+
if (millis() > _auto_off) {
76+
_display->turnOff();
77+
}
78+
}
79+
}

examples/simple_repeater/UITask.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
const char* _node_name;
10+
const char* _build_date;
11+
12+
void renderCurrScreen();
13+
public:
14+
UITask(DisplayDriver& display) : _display(&display) { _next_read = _next_refresh = 0; }
15+
void begin(const char* node_name, const char* build_date);
16+
17+
void loop();
18+
};

examples/simple_repeater/main.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@
8484
#error "need to provide a 'board' object"
8585
#endif
8686

87+
#ifdef DISPLAY_CLASS
88+
#include <helpers/ui/SSD1306Display.h>
89+
90+
static DISPLAY_CLASS display;
91+
92+
#include "UITask.h"
93+
static UITask ui_task(display);
94+
#endif
95+
8796
#define PACKET_LOG_FILE "/packet_log"
8897

8998
/* ------------------------------ Code -------------------------------- */
@@ -529,6 +538,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
529538

530539
const char* getFirmwareVer() override { return FIRMWARE_VERSION; }
531540
const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; }
541+
const char* getNodeName() { return _prefs.node_name; }
532542

533543
void savePrefs() override {
534544
#if defined(NRF52_PLATFORM)
@@ -604,6 +614,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
604614

605615
updateAdvertTimer(); // schedule next local advert
606616
}
617+
#ifdef DISPLAY_CLASS
618+
ui_task.loop();
619+
#endif
607620
}
608621
};
609622

@@ -649,6 +662,10 @@ void setup() {
649662
float tcxo = 1.6f;
650663
#endif
651664

665+
#ifdef DISPLAY_CLASS
666+
display.begin();
667+
#endif
668+
652669
#if defined(NRF52_PLATFORM)
653670
SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
654671
SPI.begin();
@@ -701,6 +718,10 @@ void setup() {
701718

702719
the_mesh.begin(fs);
703720

721+
#ifdef DISPLAY_CLASS
722+
ui_task.begin(the_mesh.getNodeName(), FIRMWARE_BUILD_DATE);
723+
#endif
724+
704725
// send out initial Advertisement to the mesh
705726
the_mesh.sendSelfAdvertisement(2000);
706727
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include "UITask.h"
2+
#include <Arduino.h>
3+
4+
#define AUTO_OFF_MILLIS 20000 // 20 seconds
5+
6+
// 'meshcore', 128x13px
7+
static const uint8_t meshcore_logo [] PROGMEM = {
8+
0x3c, 0x01, 0xe3, 0xff, 0xc7, 0xff, 0x8f, 0x03, 0x87, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe,
9+
0x3c, 0x03, 0xe3, 0xff, 0xc7, 0xff, 0x8e, 0x03, 0x8f, 0xfe, 0x3f, 0xfe, 0x1f, 0xff, 0x1f, 0xfe,
10+
0x3e, 0x03, 0xc3, 0xff, 0x8f, 0xff, 0x0e, 0x07, 0x8f, 0xfe, 0x7f, 0xfe, 0x1f, 0xff, 0x1f, 0xfc,
11+
0x3e, 0x07, 0xc7, 0x80, 0x0e, 0x00, 0x0e, 0x07, 0x9e, 0x00, 0x78, 0x0e, 0x3c, 0x0f, 0x1c, 0x00,
12+
0x3e, 0x0f, 0xc7, 0x80, 0x1e, 0x00, 0x0e, 0x07, 0x1e, 0x00, 0x70, 0x0e, 0x38, 0x0f, 0x3c, 0x00,
13+
0x7f, 0x0f, 0xc7, 0xfe, 0x1f, 0xfc, 0x1f, 0xff, 0x1c, 0x00, 0x70, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
14+
0x7f, 0x1f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
15+
0x7f, 0x3f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x1e, 0x3f, 0xfe, 0x3f, 0xf0,
16+
0x77, 0x3b, 0x87, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xfc, 0x38, 0x00,
17+
0x77, 0xfb, 0x8f, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xf8, 0x38, 0x00,
18+
0x73, 0xf3, 0x8f, 0xff, 0x0f, 0xff, 0x1c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x78, 0x7f, 0xf8,
19+
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfe, 0x3c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x3c, 0x7f, 0xf8,
20+
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfc, 0x3c, 0x0e, 0x1f, 0xf8, 0xff, 0xf8, 0x70, 0x3c, 0x7f, 0xf8,
21+
};
22+
23+
void UITask::begin(const char* node_name, const char* build_date) {
24+
_prevBtnState = HIGH;
25+
_auto_off = millis() + AUTO_OFF_MILLIS;
26+
_node_name = node_name;
27+
_build_date = build_date;
28+
_display->turnOn();
29+
}
30+
31+
void UITask::renderCurrScreen() {
32+
char tmp[80];
33+
// render 'home' screen
34+
_display->drawXbm(0, 0, meshcore_logo, 128, 13);
35+
_display->setCursor(0, 20);
36+
_display->setTextSize(1);
37+
_display->print(_node_name);
38+
39+
sprintf(tmp, "Build: %s", _build_date);
40+
_display->setCursor(0, 32);
41+
_display->print(tmp);
42+
_display->setCursor(0, 43);
43+
_display->print("< Room Server >");
44+
//_display->printf("freq : %03.2f sf %d\n", _prefs.freq, _prefs.sf);
45+
//_display->printf("bw : %03.2f cr %d\n", _prefs.bw, _prefs.cr);
46+
}
47+
48+
void UITask::loop() {
49+
#ifdef PIN_USER_BTN
50+
if (millis() >= _next_read) {
51+
int btnState = digitalRead(PIN_USER_BTN);
52+
if (btnState != _prevBtnState) {
53+
if (btnState == LOW) { // pressed?
54+
if (_display->isOn()) {
55+
// TODO: any action ?
56+
} else {
57+
_display->turnOn();
58+
}
59+
_auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer
60+
}
61+
_prevBtnState = btnState;
62+
}
63+
_next_read = millis() + 200; // 5 reads per second
64+
}
65+
#endif
66+
67+
if (_display->isOn()) {
68+
if (millis() >= _next_refresh) {
69+
_display->startFrame();
70+
renderCurrScreen();
71+
_display->endFrame();
72+
73+
_next_refresh = millis() + 1000; // refresh every second
74+
}
75+
if (millis() > _auto_off) {
76+
_display->turnOff();
77+
}
78+
}
79+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
const char* _node_name;
10+
const char* _build_date;
11+
12+
void renderCurrScreen();
13+
public:
14+
UITask(DisplayDriver& display) : _display(&display) { _next_read = _next_refresh = 0; }
15+
void begin(const char* node_name, const char* build_date);
16+
17+
void loop();
18+
};

examples/simple_room_server/main.cpp

Lines changed: 22 additions & 0 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
/* ------------------------------ Code -------------------------------- */
92101

93102
struct ClientInfo {
@@ -570,6 +579,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
570579

571580
const char* getFirmwareVer() override { return FIRMWARE_VERSION; }
572581
const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; }
582+
const char* getNodeName() { return _prefs.node_name; }
573583

574584
void savePrefs() override {
575585
#if defined(NRF52_PLATFORM)
@@ -664,6 +674,10 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
664674
updateAdvertTimer(); // schedule next local advert
665675
}
666676

677+
#ifdef DISPLAY_CLASS
678+
ui_task.loop();
679+
#endif
680+
667681
// TODO: periodically check for OLD/inactive entries in known_clients[], and evict
668682
}
669683
};
@@ -710,6 +724,10 @@ void setup() {
710724
float tcxo = 1.6f;
711725
#endif
712726

727+
#ifdef DISPLAY_CLASS
728+
display.begin();
729+
#endif
730+
713731
#if defined(NRF52_PLATFORM)
714732
SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
715733
SPI.begin();
@@ -761,6 +779,10 @@ void setup() {
761779

762780
the_mesh.begin(fs);
763781

782+
#ifdef DISPLAY_CLASS
783+
ui_task.begin(the_mesh.getNodeName(), FIRMWARE_BUILD_DATE);
784+
#endif
785+
764786
// send out initial Advertisement to the mesh
765787
the_mesh.sendSelfAdvertisement(2000);
766788
}

platformio.ini

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,19 +126,21 @@ lib_deps =
126126
extends = Heltec_lora32_v3
127127
build_flags =
128128
${Heltec_lora32_v3.build_flags}
129+
-D DISPLAY_CLASS=SSD1306Display
129130
-D ADVERT_NAME="\"Heltec Repeater\""
130131
-D ADVERT_LAT=-37.0
131132
-D ADVERT_LON=145.0
132133
-D ADMIN_PASSWORD="\"password\""
133134
-D MESH_PACKET_LOGGING=1
134135
; -D MESH_DEBUG=1
135-
build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<../examples/simple_repeater/main.cpp>
136+
build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<helpers/ui/*.cpp> +<../examples/simple_repeater>
136137

137138
[env:Heltec_v3_room_server]
138139
extends = Heltec_lora32_v3
139-
build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<../examples/simple_room_server/main.cpp>
140+
build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<helpers/ui/*.cpp> +<../examples/simple_room_server>
140141
build_flags =
141142
${Heltec_lora32_v3.build_flags}
143+
-D DISPLAY_CLASS=SSD1306Display
142144
-D ADVERT_NAME="\"Heltec Room\""
143145
-D ADVERT_LAT=-37.0
144146
-D ADVERT_LON=145.0
@@ -526,6 +528,7 @@ board_build.ldscript = boards/nrf52840_s140_v7.ld
526528
build_flags = ${nrf52840_t1000e.build_flags}
527529
-Ivariants/t1000-e
528530
-DT1000_E
531+
-D PIN_USER_BTN=6
529532
-D RADIO_CLASS=CustomLR1110
530533
-D WRAPPER_CLASS=CustomLR1110Wrapper
531534
build_src_filter = ${nrf52840_t1000e.build_src_filter}

0 commit comments

Comments
 (0)