Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Board]: Support for M5Stack Core2 ESP32 (Part 1: radio + display) #5043

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ default_envs = tbeam
;default_envs = meshtastic-diy-v1_1
;default_envs = meshtastic-dr-dev
;default_envs = m5stack-coreink
;default_envs = m5stack-core2
;default_envs = rak4631
;default_envs = rak4631_eth_gw
;default_envs = rak2560
Expand Down Expand Up @@ -165,4 +166,4 @@ lib_deps =
mprograms/[email protected]

https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
89 changes: 88 additions & 1 deletion src/ButtonThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
#if defined(M5STACK_CORE2)
#include <M5Unified.h>
#endif

#define DEBUG_BUTTONS 0
#if DEBUG_BUTTONS
Expand Down Expand Up @@ -332,4 +335,88 @@ void ButtonThread::userButtonPressedLongStop()
if (millis() > c_holdOffTime) {
btnEvent = BUTTON_EVENT_LONG_RELEASED;
}
}
}

#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
4 changes: 4 additions & 0 deletions src/ButtonThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,7 @@ class ButtonThread : public concurrency::OSThread
};

extern ButtonThread *buttonThread;

#if defined(M5STACK_CORE2)
void ScreenTouch();
#endif
18 changes: 17 additions & 1 deletion src/graphics/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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
Expand Down Expand Up @@ -1571,6 +1580,10 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
pinMode(VTFT_LEDA, OUTPUT);
digitalWrite(VTFT_LEDA, TFT_BACKLIGHT_ON);
#endif
#endif
#if defined(M5STACK_CORE2)
lboue marked this conversation as resolved.
Show resolved Hide resolved
M5.Power.Axp192.setDCDC3(1000);
M5.Display.setBrightness(130);
#endif
enabled = true;
setInterval(0); // Draw ASAP
Expand All @@ -1583,6 +1596,9 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
#endif
LOG_INFO("Turn off screen");
dispdev->displayOff();
#if defined(M5STACK_CORE2)
M5.Power.Axp192.setDCDC3(0);
#endif
#ifdef USE_ST7789
SPI1.end();
#if defined(ARCH_ESP32)
Expand Down Expand Up @@ -2747,4 +2763,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN
#endif // HAS_SCREEN
17 changes: 11 additions & 6 deletions src/graphics/TFTDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,10 @@ class LGFX : public lgfx::LGFX_Device
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.

cfg.pin_bl = TFT_BL; // Pin number to which the backlight is connected
cfg.invert = false; // true to invert the brightness of the backlight
#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

Expand Down Expand Up @@ -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
Expand All @@ -730,7 +732,8 @@ 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;
Expand Down Expand Up @@ -837,9 +840,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);
Expand All @@ -860,4 +865,4 @@ bool TFTDisplay::connect()
return true;
}

#endif
#endif
8 changes: 8 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,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 <M5Unified.h>
#endif

using namespace concurrency;

volatile static const char slipstreamTZString[] = USERPREFS_TZ_STRING;
Expand Down Expand Up @@ -804,6 +808,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)
Expand Down
2 changes: 2 additions & 0 deletions src/platform/esp32/architecture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(M5STACK_CORES3)
#define HW_VENDOR meshtastic_HardwareModel_M5STACK_CORES3
#elif defined(STATION_G1)
Expand Down
47 changes: 47 additions & 0 deletions variants/m5stack_core2/pins_arduino.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <stdint.h>

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 */
26 changes: 26 additions & 0 deletions variants/m5stack_core2/platformio.ini
Original file line number Diff line number Diff line change
@@ -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.16
m5stack/M5Unified@^0.2.0
40 changes: 40 additions & 0 deletions variants/m5stack_core2/variant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#define BUTTON_NEED_PULLUP
#define HAS_AXP192
#define I2C_SDA 21 // For AXP192
#define I2C_SCL 22 // For AXP192

#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 27 // NSS

#define USE_RF95
#define LORA_DIO0 35 // IRQ
#define LORA_RESET 25
#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

// M5Stack Core2 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