Jelajahi Sumber

enhancement on the UI and support for power off and status_led for t1000e

Florent de Lamotte 1 tahun lalu
induk
melakukan
7bb16cd7f3

+ 114 - 49
examples/companion_radio/UITask.cpp

@@ -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);
-
-    _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) {
+  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(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();
+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
+      }
+    }
+    digitalWrite(PIN_STATUS_LED, state);
+  }
+#endif
+}
+
+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();
         }
-        _auto_off = millis() + AUTO_OFF_MILLIS;   // extend auto-off timer
       }
-      _prevBtnState = btnState;
+      btn_state_change_time = millis();
+      prev_btn_state = btn_state;
     }
-    _next_read = millis() + 100;  // 10 reads per second
+    next_read = millis() + 100;  // 10 reads per second
   }
+#endif
+}
+
+void UITask::loop() {
+  buttonHandler();
+  userLedHandler();
 
-  if (_display->isOn()) {
+  if (_display != NULL && _display->isOn()) {
     if (millis() >= _next_refresh) {
       _display->startFrame();
       renderCurrScreen();

+ 15 - 4
examples/companion_radio/UITask.h

@@ -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();
-};
+};

+ 16 - 7
examples/companion_radio/main.cpp

@@ -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
 }

+ 7 - 1
platformio.ini

@@ -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>

+ 1 - 0
src/MeshCore.h

@@ -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
 };

+ 4 - 0
src/helpers/HeltecV3Board.h

@@ -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);

+ 1 - 3
src/helpers/nrf52/T1000eBoard.h

@@ -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);