mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-03-30 12:45:45 +00:00
enhancement on the UI and support for power off and status_led for t1000e
This commit is contained in:
@@ -28,7 +28,16 @@ void UITask::begin(const char* node_name, const char* build_date, uint32_t pin_c
|
||||
_node_name = node_name;
|
||||
_build_date = build_date;
|
||||
_pin_code = pin_code;
|
||||
_display->turnOn();
|
||||
if (_display != NULL) {
|
||||
_display->turnOn();
|
||||
}
|
||||
}
|
||||
|
||||
void UITask::msgRead(int msgcount) {
|
||||
_msgcount = msgcount;
|
||||
if (msgcount == 0) {
|
||||
clearMsgPreview();
|
||||
}
|
||||
}
|
||||
|
||||
void UITask::clearMsgPreview() {
|
||||
@@ -36,7 +45,9 @@ void UITask::clearMsgPreview() {
|
||||
_msg[0] = 0;
|
||||
}
|
||||
|
||||
void UITask::showMsgPreview(uint8_t path_len, const char* from_name, const char* text) {
|
||||
void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) {
|
||||
_msgcount = msgcount;
|
||||
|
||||
if (path_len == 0xFF) {
|
||||
sprintf(_origin, "(F) %s", from_name);
|
||||
} else {
|
||||
@@ -44,67 +55,121 @@ void UITask::showMsgPreview(uint8_t path_len, const char* from_name, const char*
|
||||
}
|
||||
StrHelper::strncpy(_msg, text, sizeof(_msg));
|
||||
|
||||
if (!_display->isOn()) _display->turnOn();
|
||||
_auto_off = millis() + AUTO_OFF_MILLIS; // extend the auto-off timer
|
||||
if (_display != NULL) {
|
||||
if (!_display->isOn()) _display->turnOn();
|
||||
_auto_off = millis() + AUTO_OFF_MILLIS; // extend the auto-off timer
|
||||
}
|
||||
}
|
||||
|
||||
void UITask::renderCurrScreen() {
|
||||
char tmp[80];
|
||||
if (_origin[0] && _msg[0]) {
|
||||
// render message preview
|
||||
_display->setCursor(0, 0);
|
||||
_display->setTextSize(1);
|
||||
_display->print(_node_name);
|
||||
if (_display != NULL) {
|
||||
char tmp[80];
|
||||
if (_origin[0] && _msg[0]) {
|
||||
// render message preview
|
||||
_display->setCursor(0, 0);
|
||||
_display->setTextSize(1);
|
||||
_display->print(_node_name);
|
||||
|
||||
_display->setCursor(0, 12);
|
||||
_display->print(_origin);
|
||||
_display->setCursor(0, 24);
|
||||
_display->print(_msg);
|
||||
_display->setCursor(0, 12);
|
||||
_display->print(_origin);
|
||||
_display->setCursor(0, 24);
|
||||
_display->print(_msg);
|
||||
|
||||
//_display->setCursor(100, 9); TODO
|
||||
//_display->setTextSize(2);
|
||||
//_display->printf("%d", msgs);
|
||||
} else {
|
||||
// render 'home' screen
|
||||
_display->drawXbm(0, 0, meshcore_logo, 128, 13);
|
||||
_display->setCursor(0, 20);
|
||||
_display->setTextSize(1);
|
||||
_display->print(_node_name);
|
||||
|
||||
sprintf(tmp, "Build: %s", _build_date);
|
||||
_display->setCursor(0, 32);
|
||||
_display->print(tmp);
|
||||
|
||||
if (_connected) {
|
||||
//_display->printf("freq : %03.2f sf %d\n", _prefs.freq, _prefs.sf);
|
||||
//_display->printf("bw : %03.2f cr %d\n", _prefs.bw, _prefs.cr);
|
||||
} else if (_pin_code != 0) {
|
||||
_display->setCursor(100, 9);
|
||||
_display->setTextSize(2);
|
||||
_display->setCursor(0, 43);
|
||||
sprintf(tmp, "Pin:%d", _pin_code);
|
||||
sprintf(tmp, "%d", _msgcount);
|
||||
_display->print(tmp);
|
||||
} else {
|
||||
// render 'home' screen
|
||||
_display->drawXbm(0, 0, meshcore_logo, 128, 13);
|
||||
_display->setCursor(0, 20);
|
||||
_display->setTextSize(1);
|
||||
_display->print(_node_name);
|
||||
|
||||
sprintf(tmp, "Build: %s", _build_date);
|
||||
_display->setCursor(0, 32);
|
||||
_display->print(tmp);
|
||||
|
||||
if (_connected) {
|
||||
//_display->printf("freq : %03.2f sf %d\n", _prefs.freq, _prefs.sf);
|
||||
//_display->printf("bw : %03.2f cr %d\n", _prefs.bw, _prefs.cr);
|
||||
} else if (_pin_code != 0) {
|
||||
_display->setTextSize(2);
|
||||
_display->setCursor(0, 43);
|
||||
sprintf(tmp, "Pin:%d", _pin_code);
|
||||
_display->print(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UITask::loop() {
|
||||
if (millis() >= _next_read) {
|
||||
int btnState = digitalRead(PIN_USER_BTN);
|
||||
if (btnState != _prevBtnState) {
|
||||
if (btnState == LOW) { // pressed?
|
||||
if (_display->isOn()) {
|
||||
clearMsgPreview();
|
||||
} else {
|
||||
_display->turnOn();
|
||||
}
|
||||
_auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer
|
||||
void UITask::userLedHandler() {
|
||||
#ifdef PIN_STATUS_LED
|
||||
static int state = 0;
|
||||
static int next_change = 0;
|
||||
int cur_time = millis();
|
||||
if (cur_time > next_change) {
|
||||
if (state == 0) {
|
||||
state = 1; // led on, short = unread msg
|
||||
if (_msgcount > 0) {
|
||||
next_change = cur_time + 500;
|
||||
} else {
|
||||
next_change = cur_time + 2000;
|
||||
}
|
||||
} else {
|
||||
state = 0;
|
||||
if (_board->getBattMilliVolts() > 3800) {
|
||||
next_change = cur_time + 2000;
|
||||
} else {
|
||||
next_change = cur_time + 4000; // 4s blank if bat level low
|
||||
}
|
||||
_prevBtnState = btnState;
|
||||
}
|
||||
_next_read = millis() + 100; // 10 reads per second
|
||||
digitalWrite(PIN_STATUS_LED, state);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (_display->isOn()) {
|
||||
void UITask::buttonHandler() {
|
||||
#ifdef PIN_USER_BTN
|
||||
static int prev_btn_state = HIGH;
|
||||
static unsigned long btn_state_change_time = 0;
|
||||
static unsigned long next_read = 0;
|
||||
int cur_time = millis();
|
||||
if (cur_time >= next_read) {
|
||||
int btn_state = digitalRead(PIN_USER_BTN);
|
||||
if (btn_state != prev_btn_state) {
|
||||
if (btn_state == USER_BTN_PRESSED) { // pressed?
|
||||
if (_display != NULL) {
|
||||
if (_display->isOn()) {
|
||||
clearMsgPreview();
|
||||
} else {
|
||||
_display->turnOn();
|
||||
}
|
||||
_auto_off = cur_time + AUTO_OFF_MILLIS; // extend auto-off timer
|
||||
}
|
||||
} else { // unpressed ? check pressed time ...
|
||||
if ((cur_time - btn_state_change_time) > 5000) {
|
||||
Serial.println("power off");
|
||||
#ifdef PIN_STATUS_LED
|
||||
digitalWrite(PIN_STATUS_LED, LOW);
|
||||
delay(10);
|
||||
#endif
|
||||
_board->powerOff();
|
||||
}
|
||||
}
|
||||
btn_state_change_time = millis();
|
||||
prev_btn_state = btn_state;
|
||||
}
|
||||
next_read = millis() + 100; // 10 reads per second
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void UITask::loop() {
|
||||
buttonHandler();
|
||||
userLedHandler();
|
||||
|
||||
if (_display != NULL && _display->isOn()) {
|
||||
if (millis() >= _next_refresh) {
|
||||
_display->startFrame();
|
||||
renderCurrScreen();
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <MeshCore.h>
|
||||
#include <helpers/ui/DisplayDriver.h>
|
||||
|
||||
class UITask {
|
||||
DisplayDriver* _display;
|
||||
unsigned long _next_read, _next_refresh, _auto_off;
|
||||
mesh::MainBoard* _board;
|
||||
unsigned long _next_refresh, _auto_off;
|
||||
int _prevBtnState;
|
||||
bool _connected;
|
||||
uint32_t _pin_code;
|
||||
@@ -12,14 +14,23 @@ class UITask {
|
||||
const char* _build_date;
|
||||
char _origin[62];
|
||||
char _msg[80];
|
||||
int _msgcount;
|
||||
|
||||
void renderCurrScreen();
|
||||
void buttonHandler();
|
||||
void userLedHandler();
|
||||
|
||||
public:
|
||||
UITask(DisplayDriver& display) : _display(&display) { _next_read = _next_refresh = 0; _connected = false; }
|
||||
|
||||
UITask(mesh::MainBoard* board, DisplayDriver* display) : _board(board), _display(display){
|
||||
_next_refresh = 0;
|
||||
_connected = false;
|
||||
}
|
||||
void begin(const char* node_name, const char* build_date, uint32_t pin_code);
|
||||
|
||||
void setHasConnection(bool connected) { _connected = connected; }
|
||||
void clearMsgPreview();
|
||||
void showMsgPreview(uint8_t path_len, const char* from_name, const char* text);
|
||||
void msgRead(int msgcount);
|
||||
void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount);
|
||||
void loop();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -97,12 +97,16 @@
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include "UITask.h"
|
||||
#include <helpers/ui/SSD1306Display.h>
|
||||
|
||||
static DISPLAY_CLASS display;
|
||||
|
||||
static UITask ui_task(&board, &display);
|
||||
#define HAS_UI
|
||||
#elif defined(HAS_UI)
|
||||
#include "UITask.h"
|
||||
static UITask ui_task(display);
|
||||
|
||||
static UITask ui_task(&board, NULL);
|
||||
#endif
|
||||
|
||||
// Believe it or not, this std C function is busted on some platforms!
|
||||
@@ -508,8 +512,8 @@ protected:
|
||||
} else {
|
||||
soundBuzzer();
|
||||
}
|
||||
#ifdef DISPLAY_CLASS
|
||||
ui_task.showMsgPreview(path_len, from.name, text);
|
||||
#ifdef HAS_UI
|
||||
ui_task.newMsg(path_len, from.name, text, offline_queue_len);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -550,8 +554,8 @@ protected:
|
||||
} else {
|
||||
soundBuzzer();
|
||||
}
|
||||
#ifdef DISPLAY_CLASS
|
||||
ui_task.showMsgPreview(in_path_len < 0 ? 0xFF : in_path_len, "Public", text);
|
||||
#ifdef HAS_UI
|
||||
ui_task.newMsg(in_path_len < 0 ? 0xFF : in_path_len, "Public", text, offline_queue_len);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1010,6 +1014,9 @@ public:
|
||||
int out_len;
|
||||
if ((out_len = getFromOfflineQueue(out_frame)) > 0) {
|
||||
_serial->writeFrame(out_frame, out_len);
|
||||
#ifdef HAS_UI
|
||||
ui_task.msgRead(offline_queue_len);
|
||||
#endif
|
||||
} else {
|
||||
out_frame[0] = RESP_CODE_NO_MORE_MESSAGES;
|
||||
_serial->writeFrame(out_frame, 1);
|
||||
@@ -1190,7 +1197,7 @@ public:
|
||||
checkConnections();
|
||||
}
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
#ifdef HAS_UI
|
||||
ui_task.setHasConnection(_serial->isConnected());
|
||||
ui_task.loop();
|
||||
#endif
|
||||
@@ -1315,6 +1322,8 @@ void setup() {
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
display.begin();
|
||||
#endif
|
||||
#ifdef HAS_UI
|
||||
ui_task.begin(the_mesh.getNodeName(), FIRMWARE_BUILD_DATE, the_mesh.getBLEPin());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ build_flags = -w -DNDEBUG -DRADIOLIB_STATIC_ONLY=1 -DRADIOLIB_GODMODE=1
|
||||
-D LORA_FREQ=867.5
|
||||
-D LORA_BW=250
|
||||
-D LORA_SF=10
|
||||
-D USER_BTN_PRESSED=LOW
|
||||
build_src_filter =
|
||||
+<*.cpp>
|
||||
+<helpers/*.cpp>
|
||||
@@ -774,10 +775,14 @@ board = tracker-t1000-e
|
||||
board_build.ldscript = boards/nrf52840_s140_v7.ld
|
||||
build_flags = ${nrf52840_t1000e.build_flags}
|
||||
-Ivariants/t1000-e
|
||||
-DT1000_E
|
||||
-D T1000_E
|
||||
-D PIN_USER_BTN=6
|
||||
-D USER_BTN_PRESSED=HIGH
|
||||
-D PIN_STATUS_LED=24
|
||||
-D RADIO_CLASS=CustomLR1110
|
||||
-D WRAPPER_CLASS=CustomLR1110Wrapper
|
||||
-D MAX_LORA_TX_POWER=22
|
||||
-D LORA_TX_POWER=22
|
||||
build_src_filter = ${nrf52840_t1000e.build_src_filter}
|
||||
+<helpers/*.cpp>
|
||||
+<helpers/nrf52/T1000eBoard.cpp>
|
||||
@@ -794,6 +799,7 @@ build_flags = ${t1000-e.build_flags}
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D MESH_PACKET_LOGGING=1
|
||||
-D MESH_DEBUG=1
|
||||
-D HAS_UI
|
||||
build_src_filter = ${t1000-e.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
virtual void onBeforeTransmit() { }
|
||||
virtual void onAfterTransmit() { }
|
||||
virtual void reboot() = 0;
|
||||
virtual void powerOff() { while (1) { }}; // hope it's overriden or never called ;)
|
||||
virtual uint8_t getStartupReason() const = 0;
|
||||
virtual bool startOTAUpdate() { return false; } // not supported
|
||||
};
|
||||
|
||||
@@ -67,6 +67,10 @@ public:
|
||||
esp_deep_sleep_start(); // CPU halts here and never returns!
|
||||
}
|
||||
|
||||
void powerOff() override {
|
||||
enterDeepSleep(0);
|
||||
}
|
||||
|
||||
uint16_t getBattMilliVolts() override {
|
||||
analogReadResolution(10);
|
||||
digitalWrite(PIN_ADC_CTRL, PIN_ADC_CTRL_ACTIVE);
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#include <MeshCore.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#define HAS_T1000e_POWEROFF
|
||||
|
||||
// LoRa and SPI pins
|
||||
#define P_LORA_DIO_1 (32 + 1) // P1.1
|
||||
#define P_LORA_NSS (0 + 12) // P0.12
|
||||
@@ -61,7 +59,7 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void powerOff() {
|
||||
void powerOff() override {
|
||||
#ifdef HAS_GPS
|
||||
digitalWrite(GPS_VRTC_EN, LOW);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
|
||||
Reference in New Issue
Block a user