From f6c019c948916d565e4275d98359fe1adf30ee3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Sun, 13 Oct 2024 16:48:09 +0000 Subject: [PATCH] Support for M5Stack Core2 ESP32 --- platformio.ini | 1 + src/ButtonThread.cpp | 88 ++++++++++++++++++++++++++- src/ButtonThread.h | 4 ++ src/graphics/Screen.cpp | 24 ++++++++ src/graphics/TFTDisplay.cpp | 10 ++- src/main.cpp | 8 +++ src/platform/esp32/architecture.h | 2 + variants/m5stack_core2/pins_arduino.h | 47 ++++++++++++++ variants/m5stack_core2/platformio.ini | 26 ++++++++ variants/m5stack_core2/variant.h | 44 ++++++++++++++ 10 files changed, 250 insertions(+), 4 deletions(-) create mode 100644 variants/m5stack_core2/pins_arduino.h create mode 100644 variants/m5stack_core2/platformio.ini create mode 100644 variants/m5stack_core2/variant.h diff --git a/platformio.ini b/platformio.ini index e437b572e..627ebc974 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,6 +39,7 @@ default_envs = tbeam ;default_envs = heltec_vision_master_e213 ;default_envs = heltec_vision_master_e290 ;default_envs = heltec_mesh_node_t114 +;default_envs = m5stack-core2 extra_configs = arch/*/*.ini diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp index 9e6ef55f5..4edae8484 100644 --- a/src/ButtonThread.cpp +++ b/src/ButtonThread.cpp @@ -13,6 +13,9 @@ #ifdef ARCH_PORTDUINO #include "platform/portduino/PortduinoGlue.h" #endif +#if defined(M5STACK_CORE2) +#include +#endif #define DEBUG_BUTTONS 0 #if DEBUG_BUTTONS @@ -332,4 +335,87 @@ void ButtonThread::userButtonPressedLongStop() if (millis() > c_holdOffTime) { btnEvent = BUTTON_EVENT_LONG_RELEASED; } -} \ No newline at end of file +} + +#if defined(M5STACK_CORE2) +// Define a constant +const unsigned long LONG_PRESS_THRESHOLD = 5000; // Hold the threshold +const unsigned long DOUBLE_CLICK_THRESHOLD = 1000; // Double-click the threshold +const int MAX_CLICKS = 2; // Maximum hits +// Global variable +unsigned long lastClickTime = 0; // The time of the last click +int clickCount = 0; // Click count +unsigned long touch_start_time; // Touch start time +bool is_touching = false; // Mark whether you are currently touching +void ScreenTouch(){ + M5.update(); + auto count = M5.Touch.getCount(); + if (count == 0) return; + for (std::size_t i = 0; i < count; ++i) { + auto t = M5.Touch.getDetail(i); + + // If touch starts + if (t.wasPressed()) { + touch_start_time = millis(); // Record the time when the touch began + is_touching = true; // Set to touch + } + + //Check the current touch status + if (is_touching) { + unsigned long duration = millis() - touch_start_time; + if (duration >= LONG_PRESS_THRESHOLD) { + LOG_INFO("Long Press Detected\n"); + powerFSM.trigger(EVENT_PRESS); + screen->startAlert("Shutting down..."); + screen->forceDisplay(true); + // Executive logic, such as shutdown, display menu, etc + // To avoid duplicate detection, set is_touching to false here + is_touching = false; + M5.Speaker.tone(3000, 300); + delay(1000); + M5.Power.powerOff(); + } + } + // Check if the touch just ended + if (t.wasReleased()) { + if (is_touching) { + unsigned long duration = millis() - touch_start_time; + if (duration < LONG_PRESS_THRESHOLD) { + unsigned long currentTime = millis(); + // Check whether it is a double click + if (currentTime - lastClickTime <= DOUBLE_CLICK_THRESHOLD) { + clickCount++; + if (clickCount == MAX_CLICKS) { + LOG_INFO("Double Click Detected\n"); + M5.Speaker.tone(2000, 100); + service->refreshLocalMeshNode(); + auto sentPosition = service->trySendPosition(NODENUM_BROADCAST, true); + if (screen) { + if (sentPosition) + screen->print("Sent ad-hoc position\n"); + else + screen->print("Sent ad-hoc nodeinfo\n"); + screen->forceDisplay(true); // Force a new UI frame, then force an EInk update + } + clickCount = 0; + } + } else { + clickCount = 1; + } + + lastClickTime = currentTime; // Update last click time + } + } + // Reset the touch status + is_touching = false; + } + // You can add more status checks, such as sliding and dragging + if (t.wasFlickStart()) { + LOG_INFO("Flick Start Detected\n"); + M5.Speaker.tone(1000, 100); + powerFSM.trigger(EVENT_PRESS); + + } + } +} +#endif \ No newline at end of file diff --git a/src/ButtonThread.h b/src/ButtonThread.h index 9cd7b3dac..4f1507af4 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -66,3 +66,7 @@ class ButtonThread : public concurrency::OSThread }; extern ButtonThread *buttonThread; + +#if defined(M5STACK_CORE2) +void ScreenTouch(); +#endif \ No newline at end of file diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 3c0230330..36a2443d1 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -66,6 +66,15 @@ along with this program. If not, see . #include "platform/portduino/PortduinoGlue.h" #endif +#if defined(M5STACK_CORE2) +#include "M5Unified.h" +#define OLED_BLACK OLEDDISPLAY_COLOR::BLACK +#define OLED_WHITE OLEDDISPLAY_COLOR::WHITE +#else + #define OLED_BLACK BLACK + #define OLED_WHITE WHITE +#endif + using namespace meshtastic; /** @todo remove */ namespace graphics @@ -1621,6 +1630,14 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) pinMode(VTFT_LEDA, OUTPUT); digitalWrite(VTFT_LEDA, TFT_BACKLIGHT_ON); #endif +#endif +#ifdef TFT_BL + pinMode(TFT_BL, OUTPUT); + digitalWrite(TFT_BL, HIGH); +#endif +#if defined(M5STACK_CORE2) + M5.Power.Axp192.setDCDC3(1000); + M5.Display.setBrightness(130); #endif enabled = true; setInterval(0); // Draw ASAP @@ -1633,6 +1650,13 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) #endif LOG_INFO("Turning off screen\n"); dispdev->displayOff(); +#ifdef TFT_BL + pinMode(TFT_BL, OUTPUT); + digitalWrite(TFT_BL, LOW); +#endif +#if defined(M5STACK_CORE2) + M5.Power.Axp192.setDCDC3(0); +#endif #ifdef USE_ST7789 SPI1.end(); #if defined(ARCH_ESP32) diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 0c32a7c32..844e1b022 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -327,7 +327,9 @@ class LGFX : public lgfx::LGFX_Device { auto cfg = _light_instance.config(); // Gets a structure for backlight settings. +#if !defined(M5STACK_CORE2) cfg.pin_bl = TFT_BL; // Pin number to which the backlight is connected +#endif cfg.invert = false; // true to invert the brightness of the backlight // cfg.freq = 44100; // PWM frequency of backlight // cfg.pwm_channel = 1; // PWM channel number to use @@ -718,7 +720,7 @@ void TFTDisplay::sendCommand(uint8_t com) display(true); if (settingsMap[displayBacklight] > 0) digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON); -#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) +#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) && !defined(M5STACK_CORE2) tft->wakeup(); tft->powerSaveOff(); #endif @@ -730,7 +732,7 @@ void TFTDisplay::sendCommand(uint8_t com) unphone.backlight(true); // using unPhone library #endif #ifdef RAK14014 -#elif !defined(M5STACK) && !defined(ST7789_CS) // T-Deck gets brightness set in Screen.cpp in the handleSetOn function +#elif !defined(M5STACK) && !defined(ST7789_CS) && !defined(M5STACK_CORE2) // T-Deck gets brightness set in Screen.cpp in the handleSetOn function tft->setBrightness(172); #endif break; @@ -837,9 +839,11 @@ bool TFTDisplay::connect() unphone.backlight(true); // using unPhone library #endif +#if !defined(M5STACK_CORE2) tft->init(); +#endif -#if defined(M5STACK) +#if defined(M5STACK) || defined(M5STACK_CORE2) tft->setRotation(0); #elif defined(RAK14014) tft->setRotation(1); diff --git a/src/main.cpp b/src/main.cpp index 45c6498ce..8d1dc91d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,6 +118,10 @@ AudioThread *audioThread = nullptr; float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; // if TCXO is optional, put this here so it can be changed further down. #endif +#if defined(M5STACK_CORE2) +#include +#endif + using namespace concurrency; volatile static const char slipstreamTZString[] = USERPREFS_TZ_STRING; @@ -795,6 +799,10 @@ void setup() RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_NO_AXP192); // Record a hardware fault for missing hardware #endif +#if defined(M5STACK_CORE2) + M5.begin(); +#endif + #if !MESHTASTIC_EXCLUDE_I2C // Don't call screen setup until after nodedb is setup (because we need // the current region name) diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 01f416629..8c9917dd9 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -104,6 +104,8 @@ #define HW_VENDOR meshtastic_HardwareModel_NANO_G1 #elif defined(M5STACK) #define HW_VENDOR meshtastic_HardwareModel_M5STACK +#elif defined(M5STACK_CORE2) +#define HW_VENDOR meshtastic_HardwareModel_M5STACK_CORE2 #elif defined(STATION_G1) #define HW_VENDOR meshtastic_HardwareModel_STATION_G1 #elif defined(DR_DEV) diff --git a/variants/m5stack_core2/pins_arduino.h b/variants/m5stack_core2/pins_arduino.h new file mode 100644 index 000000000..86c6b812a --- /dev/null +++ b/variants/m5stack_core2/pins_arduino.h @@ -0,0 +1,47 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t TXD2 = 17; +static const uint8_t RXD2 = 16; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 33; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 38; +static const uint8_t SCK = 18; + +static const uint8_t G23 = 23; +static const uint8_t G19 = 19; +static const uint8_t G18 = 18; +static const uint8_t G3 = 3; +static const uint8_t G16 = 16; +static const uint8_t G21 = 21; +static const uint8_t G2 = 2; +static const uint8_t G12 = 12; +static const uint8_t G15 = 15; +static const uint8_t G35 = 35; +static const uint8_t G36 = 36; +static const uint8_t G25 = 25; +static const uint8_t G26 = 26; +static const uint8_t G1 = 1; +static const uint8_t G17 = 17; +static const uint8_t G22 = 22; +static const uint8_t G5 = 5; +static const uint8_t G13 = 13; +static const uint8_t G0 = 0; +static const uint8_t G34 = 34; + +static const uint8_t DAC1 = 25; +static const uint8_t DAC2 = 26; + +static const uint8_t ADC1 = 35; +static const uint8_t ADC2 = 36; + +#endif /* Pins_Arduino_h */ diff --git a/variants/m5stack_core2/platformio.ini b/variants/m5stack_core2/platformio.ini new file mode 100644 index 000000000..cae516ad2 --- /dev/null +++ b/variants/m5stack_core2/platformio.ini @@ -0,0 +1,26 @@ +[env:m5stack-core2] +extends = esp32_base +board = m5stack-core-esp32 +monitor_filters = esp32_exception_decoder +build_src_filter = + ${esp32_base.build_src_filter} +build_flags = + ${esp32_base.build_flags} -I variants/m5stack_core2 + -DILI9341_DRIVER + -DM5STACK_CORE2 + -DUSER_SETUP_LOADED + -DTFT_SDA_READ + -DTFT_DRIVER=0x9341 + -DTFT_MISO=38 + -DTFT_MOSI=23 + -DTFT_SCLK=18 + -DTFT_CS=5 + -DTFT_DC=15 + -DTFT_RST=-1 + -DSPI_FREQUENCY=40000000 + -DSPI_READ_FREQUENCY=16000000 + -DDISABLE_ALL_LIBRARY_WARNINGS +lib_deps = + ${esp32_base.lib_deps} + lovyan03/LovyanGFX@^1.1.8 + m5stack/M5Unified@^0.1.14 \ No newline at end of file diff --git a/variants/m5stack_core2/variant.h b/variants/m5stack_core2/variant.h new file mode 100644 index 000000000..cdd10dc76 --- /dev/null +++ b/variants/m5stack_core2/variant.h @@ -0,0 +1,44 @@ +// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep + + +// #define BUTTON_PIN 39 // 38, 37 +// #define BUTTON_PIN 0 +#define BUTTON_NEED_PULLUP +// #define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin. + +//#define BUTTON_PIN + +//#define PIN_BUZZER 25 +#undef LORA_SCK +#undef LORA_MISO +#undef LORA_MOSI +#undef LORA_CS + +#define LORA_SCK 18 +#define LORA_MISO 38 +#define LORA_MOSI 23 +#define LORA_CS 33 //NSS + +#define USE_RF95 +#define LORA_DIO0 35 // IRQ +#define LORA_RESET 19 +#define LORA_DIO1 RADIOLIB_NC // Not really used +#define LORA_DIO2 RADIOLIB_NC // Not really used + +// This board has different GPS pins than all other boards +#undef GPS_RX_PIN +#undef GPS_TX_PIN +#define GPS_RX_PIN 13 +#define GPS_TX_PIN 14 + +#define TFT_HEIGHT 240 +#define TFT_WIDTH 320 +#define TFT_OFFSET_X 0 +#define TFT_OFFSET_Y 0 +#define TFT_BUSY -1 +#define TFT_OFFSET_ROTATION 0 +// LCD screens are slow, so slowdown the wipe so it looks better +#define SCREEN_TRANSITION_FRAMERATE 30 // fps +// Picomputer gets a white on black display +#define TFT_MESH COLOR565 (0xA0, 0xFF, 0x00)//(0x94, 0xEA, 0x67) +#define ILI9341_SPI_HOST VSPI_HOST // VSPI_HOST or HSPI_HOST \ No newline at end of file