Add Tab5 basic touch example
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
.pio/
|
||||
.vscode/
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# M5Stack Tab5 Basic Touch
|
||||
|
||||
The first project in a small, beginner-friendly Tab5 basics series. It shows
|
||||
the minimum useful M5Unified/M5GFX pattern for drawing a screen and reacting
|
||||
to capacitive touch.
|
||||
|
||||
The screen contains a header, divider line, status message, and two large
|
||||
touch targets:
|
||||
|
||||
- **Left / Sun:** changes the left panel colour and increments its counter.
|
||||
- **Right / Moon:** toggles the moon symbol and increments its counter.
|
||||
|
||||
M5Unified and M5GFX are used directly instead of LVGL. That keeps this first
|
||||
example small enough to read from top to bottom while still using the native
|
||||
Tab5 display and touch support. LVGL is a better fit for a later, widget-heavy
|
||||
example rather than the foundational touch example.
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
pio run
|
||||
pio run --target upload
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[env:tab5]
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.21-2/platform-espressif32.zip
|
||||
board = esp32-p4-evboard
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
upload_speed = 1500000
|
||||
board_build.mcu = esp32p4
|
||||
board_build.flash_mode = qio
|
||||
build_flags =
|
||||
-DBOARD_HAS_PSRAM
|
||||
-DCORE_DEBUG_LEVEL=3
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
-DARDUINO_USB_MODE=1
|
||||
lib_deps =
|
||||
https://github.com/M5Stack/M5Unified.git
|
||||
https://github.com/M5Stack/M5GFX.git
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
#include <Arduino.h>
|
||||
#include <M5Unified.h>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint16_t BG = 0x0841;
|
||||
constexpr uint16_t HEADER = 0x18E3;
|
||||
constexpr uint16_t LEFT_BLUE = 0x2B8E;
|
||||
constexpr uint16_t LEFT_GREEN = 0x3D88;
|
||||
constexpr uint16_t RIGHT_PURPLE = 0x620B;
|
||||
constexpr uint16_t RIGHT_ORANGE = 0xC3E0;
|
||||
constexpr uint16_t ACCENT = 0x2E9F;
|
||||
constexpr uint16_t MUTED = 0xBDF7;
|
||||
|
||||
struct Rect {
|
||||
int32_t x, y, w, h;
|
||||
|
||||
bool contains(int32_t px, int32_t py) const {
|
||||
return px >= x && px < x + w && py >= y && py < y + h;
|
||||
}
|
||||
};
|
||||
|
||||
Rect leftPanel;
|
||||
Rect rightPanel;
|
||||
uint32_t leftTouches = 0;
|
||||
uint32_t rightTouches = 0;
|
||||
bool leftAlternate = false;
|
||||
bool moonFull = false;
|
||||
|
||||
void drawText(const char* value, int32_t x, int32_t y, textdatum_t datum,
|
||||
const lgfx::IFont* font, uint16_t color) {
|
||||
M5.Display.setFont(font);
|
||||
M5.Display.setTextDatum(datum);
|
||||
M5.Display.setTextColor(color); // Transparent glyph background.
|
||||
M5.Display.drawString(value, x, y);
|
||||
}
|
||||
|
||||
void drawSun(int32_t x, int32_t y, uint16_t color) {
|
||||
M5.Display.fillCircle(x, y, 42, color);
|
||||
for (int angle = 0; angle < 360; angle += 45) {
|
||||
float radians = angle * DEG_TO_RAD;
|
||||
int32_t x1 = x + cosf(radians) * 58;
|
||||
int32_t y1 = y + sinf(radians) * 58;
|
||||
int32_t x2 = x + cosf(radians) * 82;
|
||||
int32_t y2 = y + sinf(radians) * 82;
|
||||
M5.Display.drawWideLine(x1, y1, x2, y2, 8, color);
|
||||
}
|
||||
}
|
||||
|
||||
void drawMoon(int32_t x, int32_t y, uint16_t panelColor) {
|
||||
M5.Display.fillCircle(x, y, 72, TFT_WHITE);
|
||||
if (!moonFull) {
|
||||
M5.Display.fillCircle(x + 34, y - 20, 68, panelColor);
|
||||
}
|
||||
}
|
||||
|
||||
void drawPanel(const Rect& area, bool left) {
|
||||
uint16_t fill = left ? (leftAlternate ? LEFT_GREEN : LEFT_BLUE)
|
||||
: (moonFull ? RIGHT_ORANGE : RIGHT_PURPLE);
|
||||
M5.Display.fillRoundRect(area.x, area.y, area.w, area.h, 26, fill);
|
||||
M5.Display.drawRoundRect(area.x, area.y, area.w, area.h, 26, TFT_WHITE);
|
||||
|
||||
if (left) {
|
||||
drawSun(area.x + area.w / 2, area.y + 142, TFT_YELLOW);
|
||||
} else {
|
||||
drawMoon(area.x + area.w / 2, area.y + 142, fill);
|
||||
}
|
||||
|
||||
drawText(left ? "LEFT" : "RIGHT", area.x + area.w / 2, area.y + 270,
|
||||
middle_center, &fonts::FreeSansBold24pt7b, TFT_WHITE);
|
||||
drawText(left ? "Tap to change colour" : "Tap to change the moon",
|
||||
area.x + area.w / 2, area.y + 324, middle_center,
|
||||
&fonts::FreeSans12pt7b, TFT_WHITE);
|
||||
|
||||
char count[48];
|
||||
snprintf(count, sizeof(count), "Touches: %lu",
|
||||
static_cast<unsigned long>(left ? leftTouches : rightTouches));
|
||||
drawText(count, area.x + area.w / 2, area.y + 378, middle_center,
|
||||
&fonts::FreeSansBold12pt7b, TFT_WHITE);
|
||||
}
|
||||
|
||||
void drawStatus(const char* message) {
|
||||
M5.Display.fillRect(28, 100, M5.Display.width() - 56, 50, BG);
|
||||
drawText(message, M5.Display.width() / 2, 125, middle_center,
|
||||
&fonts::FreeSans12pt7b, MUTED);
|
||||
}
|
||||
|
||||
void drawScreen() {
|
||||
int32_t width = M5.Display.width();
|
||||
int32_t height = M5.Display.height();
|
||||
constexpr int32_t margin = 28;
|
||||
constexpr int32_t gap = 22;
|
||||
|
||||
leftPanel = {margin, 166, (width - margin * 2 - gap) / 2, height - 194};
|
||||
rightPanel = {leftPanel.x + leftPanel.w + gap, leftPanel.y, leftPanel.w,
|
||||
leftPanel.h};
|
||||
|
||||
M5.Display.fillScreen(BG);
|
||||
M5.Display.fillRect(0, 0, width, 86, HEADER);
|
||||
M5.Display.fillRect(0, 84, width, 3, ACCENT);
|
||||
drawText("TAB5 BASIC TOUCH", 28, 40, middle_left,
|
||||
&fonts::FreeSansBold24pt7b, TFT_WHITE);
|
||||
drawText("M5UNIFIED + M5GFX", width - 28, 40, middle_right,
|
||||
&fonts::FreeSans12pt7b, MUTED);
|
||||
drawStatus("Touch either large panel");
|
||||
drawPanel(leftPanel, true);
|
||||
drawPanel(rightPanel, false);
|
||||
}
|
||||
|
||||
void handleTouch(int32_t x, int32_t y) {
|
||||
if (leftPanel.contains(x, y)) {
|
||||
++leftTouches;
|
||||
leftAlternate = !leftAlternate;
|
||||
drawPanel(leftPanel, true);
|
||||
drawStatus("LEFT touched: colour changed");
|
||||
Serial.printf("LEFT touched at %ld,%ld; count=%lu\n", (long)x, (long)y,
|
||||
(unsigned long)leftTouches);
|
||||
} else if (rightPanel.contains(x, y)) {
|
||||
++rightTouches;
|
||||
moonFull = !moonFull;
|
||||
drawPanel(rightPanel, false);
|
||||
drawStatus("RIGHT touched: moon changed");
|
||||
Serial.printf("RIGHT touched at %ld,%ld; count=%lu\n", (long)x, (long)y,
|
||||
(unsigned long)rightTouches);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
auto config = M5.config();
|
||||
M5.begin(config);
|
||||
M5.Display.setRotation(1);
|
||||
M5.Display.setColorDepth(16);
|
||||
M5.Display.setBrightness(180);
|
||||
drawScreen();
|
||||
Serial.println("M5Stack Tab5 Basic Touch ready");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
M5.update();
|
||||
auto touch = M5.Touch.getDetail();
|
||||
if (touch.wasReleased()) {
|
||||
handleTouch(touch.x, touch.y);
|
||||
}
|
||||
delay(8);
|
||||
}
|
||||
Reference in New Issue
Block a user