Preliminary Thinknode M4 Support (#8754)

* Preliminary Thinknode M4 Support

* oops

* Fix RF switch TX configuration

* trunk'd

* GPS fix for M4

* Battery handling and LED for M4

* Trunk

* Drop debug warnings

* Make Red LED notification

* Merge cleanup

* Make white LEDs flash during charge

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
This commit is contained in:
Thomas Göttgens
2026-01-15 04:36:53 +01:00
committed by GitHub
parent a6a80b067f
commit 233e6acc85
14 changed files with 475 additions and 15 deletions

View File

@@ -64,8 +64,9 @@ SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
#if defined(TTGO_T_ECHO) || defined(TTGO_T_ECHO_PLUS) || defined(CANARYONE) || defined(MESHLINK) || \
defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M5) || defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE) || \
defined(ELECROW_ThinkNode_M3) || defined(MUZI_BASE)
defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M4) || defined(ELECROW_ThinkNode_M5) || \
defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE) || defined(ELECROW_ThinkNode_M3) || defined(MUZI_BASE)
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial")
{
api_type = TYPE_SERIAL;
@@ -205,8 +206,9 @@ int32_t SerialModule::runOnce()
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
#elif !defined(TTGO_T_ECHO) && !defined(TTGO_T_ECHO_PLUS) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && \
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && \
!defined(MUZI_BASE)
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M4) && \
!defined(ELECROW_ThinkNode_M5) && !defined(MUZI_BASE)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
@@ -263,7 +265,8 @@ int32_t SerialModule::runOnce()
}
#if !defined(TTGO_T_ECHO) && !defined(TTGO_T_ECHO_PLUS) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && !defined(MUZI_BASE)
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M4) && \
!defined(ELECROW_ThinkNode_M5) && !defined(MUZI_BASE)
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
processWXSerial();
@@ -539,7 +542,10 @@ void SerialModule::processWXSerial()
{
#if !defined(TTGO_T_ECHO) && !defined(TTGO_T_ECHO_PLUS) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && \
!defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
!defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && !defined(ARCH_STM32WL) && !defined(MUZI_BASE)
!defined(ELECROW_ThinkNode_M3) && \
!defined(ELECROW_ThinkNode_M4) && \
!defined(ELECROW_ThinkNode_M5) && !defined(ARCH_STM32WL) && !defined(MUZI_BASE)
static unsigned int lastAveraged = 0;
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
static double dir_sum_sin = 0;

View File

@@ -13,6 +13,8 @@ StatusLEDModule::StatusLEDModule() : concurrency::OSThread("StatusLEDModule")
{
bluetoothStatusObserver.observe(&bluetoothStatus->onNewStatus);
powerStatusObserver.observe(&powerStatus->onNewStatus);
if (inputBroker)
inputObserver.observe(inputBroker);
}
int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
@@ -60,6 +62,12 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
return 0;
};
int StatusLEDModule::handleInputEvent(const InputEvent *event)
{
lastUserbuttonTime = millis();
return 0;
}
int32_t StatusLEDModule::runOnce()
{
my_interval = 1000;
@@ -103,6 +111,21 @@ int32_t StatusLEDModule::runOnce()
PAIRING_LED_state = LED_STATE_ON;
}
bool chargeIndicatorLED1 = LED_STATE_OFF;
bool chargeIndicatorLED2 = LED_STATE_OFF;
bool chargeIndicatorLED3 = LED_STATE_OFF;
bool chargeIndicatorLED4 = LED_STATE_OFF;
if (lastUserbuttonTime + 10 * 1000 > millis() || CHARGE_LED_state == LED_STATE_ON) {
// should this be off at very low percentages?
chargeIndicatorLED1 = LED_STATE_ON;
if (powerStatus && powerStatus->getBatteryChargePercent() >= 25)
chargeIndicatorLED2 = LED_STATE_ON;
if (powerStatus && powerStatus->getBatteryChargePercent() >= 50)
chargeIndicatorLED3 = LED_STATE_ON;
if (powerStatus && powerStatus->getBatteryChargePercent() >= 75)
chargeIndicatorLED4 = LED_STATE_ON;
}
#ifdef LED_CHARGE
digitalWrite(LED_CHARGE, CHARGE_LED_state);
#endif
@@ -111,5 +134,18 @@ int32_t StatusLEDModule::runOnce()
digitalWrite(LED_PAIRING, PAIRING_LED_state);
#endif
#ifdef Battery_LED_1
digitalWrite(Battery_LED_1, chargeIndicatorLED1);
#endif
#ifdef Battery_LED_2
digitalWrite(Battery_LED_2, chargeIndicatorLED2);
#endif
#ifdef Battery_LED_3
digitalWrite(Battery_LED_3, chargeIndicatorLED3);
#endif
#ifdef Battery_LED_4
digitalWrite(Battery_LED_4, chargeIndicatorLED4);
#endif
return (my_interval);
}

View File

@@ -5,6 +5,7 @@
#include "PowerStatus.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include "input/InputBroker.h"
#include <Arduino.h>
#include <functional>
@@ -17,6 +18,8 @@ class StatusLEDModule : private concurrency::OSThread
int handleStatusUpdate(const meshtastic::Status *);
int handleInputEvent(const InputEvent *arg);
protected:
unsigned int my_interval = 1000; // interval in millisconds
virtual int32_t runOnce() override;
@@ -25,12 +28,15 @@ class StatusLEDModule : private concurrency::OSThread
CallbackObserver<StatusLEDModule, const meshtastic::Status *>(this, &StatusLEDModule::handleStatusUpdate);
CallbackObserver<StatusLEDModule, const meshtastic::Status *> powerStatusObserver =
CallbackObserver<StatusLEDModule, const meshtastic::Status *>(this, &StatusLEDModule::handleStatusUpdate);
CallbackObserver<StatusLEDModule, const InputEvent *> inputObserver =
CallbackObserver<StatusLEDModule, const InputEvent *>(this, &StatusLEDModule::handleInputEvent);
private:
bool CHARGE_LED_state = LED_STATE_OFF;
bool PAIRING_LED_state = LED_STATE_OFF;
uint32_t PAIRING_LED_starttime = 0;
uint32_t lastUserbuttonTime = 0;
uint32_t POWER_LED_starttime = 0;
bool doing_fast_blink = false;