Skip to content

Commit 619b5aa

Browse files
M5Stack Tab5 support (#449)
* **New Features** * Added support for M5Stack Tab5: integrated display (ILI9881C MIPI-DSI), touch, and SD card. * **User Interface** * Changed toolbar label from "External Apps" to "Installed Apps." * **Improvements** * Clarified boot log messages ("Init boot"/"Init boot failed") for better diagnostics. * Firmware build matrix and configuration updated to include the M5Stack Tab5 target.
1 parent 10381b1 commit 619b5aa

File tree

19 files changed

+946
-5
lines changed

19 files changed

+946
-5
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ jobs:
6262
{ id: m5stack-cores3, arch: esp32s3 },
6363
{ id: m5stack-stickc-plus, arch: esp32 },
6464
{ id: m5stack-stickc-plus2, arch: esp32 },
65+
{ id: m5stack-tab5, arch: esp32p4 },
6566
{ id: unphone, arch: esp32s3 },
6667
{ id: waveshare-esp32-s3-geek, arch: esp32s3 },
6768
{ id: waveshare-s3-lcd-13, arch: esp32s3 },

Devices/guition-jc1060p470ciwy/Source/devices/Display.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,5 @@ std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
6161
});
6262

6363
const auto display = std::make_shared<Jd9165Display>(configuration);
64-
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
64+
return std::static_pointer_cast<tt::hal::display::DisplayDevice>(display);
6565
}

Devices/guition-jc1060p470ciwy/device.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[general]
22
vendor=Guition
3-
name=JC1060P470CIWY
3+
name=JC1060P470C-I-W-Y
44

55
[hardware]
66
target=ESP32P4
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
2+
3+
idf_component_register(
4+
SRCS ${SOURCE_FILES}
5+
INCLUDE_DIRS "Source"
6+
REQUIRES Tactility esp_lvgl_port esp_lcd EspLcdCompat esp_lcd_ili9881c GT911 PwmBacklight driver vfs fatfs
7+
)
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#include "devices/Display.h"
2+
#include "devices/SdCard.h"
3+
4+
#include <Tactility/hal/Configuration.h>
5+
6+
using namespace tt::hal;
7+
8+
static const auto LOGGER = tt::Logger("Tab5");
9+
10+
static DeviceVector createDevices() {
11+
return {
12+
createDisplay(),
13+
createSdCard(),
14+
};
15+
}
16+
17+
static bool initBoot() {
18+
/*
19+
PI4IOE5V6408-1 (0x43)
20+
- Bit 0: RF internal/external switch
21+
- Bit 1: Speaker enable
22+
- Bit 2: External 5V bus enable
23+
- Bit 3: /
24+
- Bit 4: LCD reset
25+
- Bit 5: Touch reset
26+
- Bit 6: Camera reset
27+
- Bit 7: Headphone detect
28+
29+
PI4IOE5V6408-2 (0x44)
30+
- Bit 0: C6 WLAN enable
31+
- Bit 1: /
32+
- Bit 2: /
33+
- Bit 3: USB-A 5V enable
34+
- Bit 4: Device power: PWROFF_PLUSE
35+
- Bit 5: IP2326: nCHG_QC_EN
36+
- Bit 6: IP2326: CHG_STAT_LED
37+
- Bit 7: IP2326: CHG_EN
38+
*/
39+
40+
// Init byte arrays adapted from https://github.com/m5stack/M5GFX/blob/03565ccc96cb0b73c8b157f5ec3fbde439b034ad/src/M5GFX.cpp
41+
static constexpr uint8_t reg_data_io1_1[] = {
42+
0x03, 0b01111111, // PI4IO_REG_IO_DIR
43+
0x05, 0b01000110, // PI4IO_REG_OUT_SET (bit4=LCD Reset, bit5=GT911 TouchReset -> LOW)
44+
0x07, 0b00000000, // PI4IO_REG_OUT_H_IM
45+
0x0D, 0b01111111, // PI4IO_REG_PULL_SEL
46+
0x0B, 0b01111111, // PI4IO_REG_PULL_EN
47+
};
48+
49+
static constexpr uint8_t reg_data_io1_2[] = {
50+
0x05, 0b01110110, // PI4IO_REG_OUT_SET (bit4=LCD Reset, bit5=GT911 TouchReset -> HIGH)
51+
};
52+
53+
static constexpr uint8_t reg_data_io2[] = {
54+
0x03, 0b10111001, // PI4IO_REG_IO_DIR
55+
0x07, 0b00000110, // PI4IO_REG_OUT_H_IM
56+
0x0D, 0b10111001, // PI4IO_REG_PULL_SEL
57+
0x0B, 0b11111001, // PI4IO_REG_PULL_EN
58+
0x09, 0b01000000, // PI4IO_REG_IN_DEF_STA
59+
0x11, 0b10111111, // PI4IO_REG_INT_MASK
60+
0x05, 0b10001001, // PI4IO_REG_OUT_SET (enable WiFi, USB-A 5V and CHG_EN)
61+
};
62+
63+
constexpr auto IO_EXPANDER1_ADDRESS = 0x43;
64+
if (!i2c::masterWriteRegisterArray(I2C_NUM_0, IO_EXPANDER1_ADDRESS, reg_data_io1_1, sizeof(reg_data_io1_1))) {
65+
LOGGER.error("IO expander 1 init failed in phase 1");
66+
return false;
67+
}
68+
69+
constexpr auto IO_EXPANDER2_ADDRESS = 0x44;
70+
if (!i2c::masterWriteRegisterArray(I2C_NUM_0, IO_EXPANDER2_ADDRESS, reg_data_io2, sizeof(reg_data_io2))) {
71+
LOGGER.error("IO expander 2 init failed");
72+
return false;
73+
}
74+
75+
// The M5Stack code applies this, but it's not known why
76+
// TODO: Remove and test it extensively
77+
tt::kernel::delayTicks(10);
78+
79+
if (!i2c::masterWriteRegisterArray(I2C_NUM_0, IO_EXPANDER1_ADDRESS, reg_data_io1_2, sizeof(reg_data_io1_2))) {
80+
LOGGER.error("IO expander 1 init failed in phase 2");
81+
return false;
82+
}
83+
84+
return true;
85+
}
86+
87+
extern const Configuration hardwareConfiguration = {
88+
.initBoot = initBoot,
89+
.createDevices = createDevices,
90+
.i2c = {
91+
i2c::Configuration {
92+
.name = "Internal",
93+
.port = I2C_NUM_0,
94+
.initMode = i2c::InitMode::ByTactility,
95+
.isMutable = false,
96+
.config = (i2c_config_t) {
97+
.mode = I2C_MODE_MASTER,
98+
.sda_io_num = GPIO_NUM_31,
99+
.scl_io_num = GPIO_NUM_32,
100+
.sda_pullup_en = true,
101+
.scl_pullup_en = true,
102+
.master = {
103+
.clk_speed = 400000
104+
},
105+
.clk_flags = 0
106+
}
107+
},
108+
i2c::Configuration {
109+
.name = "Port A",
110+
.port = I2C_NUM_1,
111+
.initMode = i2c::InitMode::ByTactility,
112+
.isMutable = false,
113+
.config = (i2c_config_t) {
114+
.mode = I2C_MODE_MASTER,
115+
.sda_io_num = GPIO_NUM_53,
116+
.scl_io_num = GPIO_NUM_54,
117+
.sda_pullup_en = true,
118+
.scl_pullup_en = true,
119+
.master = {
120+
.clk_speed = 400000
121+
},
122+
.clk_flags = 0
123+
}
124+
}
125+
},
126+
.spi = {
127+
// SDCard
128+
spi::Configuration {
129+
.device = SPI3_HOST,
130+
.dma = SPI_DMA_CH_AUTO,
131+
.config = {
132+
.mosi_io_num = GPIO_NUM_44,
133+
.miso_io_num = GPIO_NUM_39,
134+
.sclk_io_num = GPIO_NUM_43,
135+
.quadwp_io_num = GPIO_NUM_NC,
136+
.quadhd_io_num = GPIO_NUM_NC,
137+
.data4_io_num = GPIO_NUM_NC,
138+
.data5_io_num = GPIO_NUM_NC,
139+
.data6_io_num = GPIO_NUM_NC,
140+
.data7_io_num = GPIO_NUM_NC,
141+
.data_io_default_level = false,
142+
.max_transfer_sz = 0,
143+
.flags = 0,
144+
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
145+
.intr_flags = 0
146+
},
147+
.initMode = spi::InitMode::ByTactility,
148+
.isMutable = false,
149+
.lock = nullptr
150+
}
151+
}
152+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extern "C" {
2+
3+
extern void register_device_drivers() {
4+
/* NO-OP */
5+
}
6+
7+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include "Display.h"
2+
#include "Ili9881cDisplay.h"
3+
4+
#include <Gt911Touch.h>
5+
#include <PwmBacklight.h>
6+
#include <Tactility/Logger.h>
7+
#include <Tactility/Mutex.h>
8+
#include <Tactility/hal/gpio/Gpio.h>
9+
10+
constexpr auto LCD_PIN_RESET = GPIO_NUM_0; // Match P4 EV board reset line
11+
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_22;
12+
13+
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
14+
auto configuration = std::make_unique<Gt911Touch::Configuration>(
15+
I2C_NUM_0,
16+
720,
17+
1280,
18+
false, // swapXY
19+
false, // mirrorX
20+
false, // mirrorY
21+
GPIO_NUM_NC, // reset pin
22+
GPIO_NUM_NC // "GPIO_NUM_23 cannot be used due to resistor to 3V3" https://github.com/espressif/esp-bsp/blob/ad668c765cbad177495a122181df0a70ff9f8f61/bsp/m5stack_tab5/src/m5stack_tab5.c#L76234
23+
);
24+
25+
return std::make_shared<Gt911Touch>(std::move(configuration));
26+
}
27+
28+
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
29+
// Initialize PWM backlight
30+
if (!driver::pwmbacklight::init(LCD_PIN_BACKLIGHT, 5000, LEDC_TIMER_1, LEDC_CHANNEL_0)) {
31+
tt::Logger("Tab5").warn("Failed to initialize backlight");
32+
}
33+
34+
auto touch = createTouch();
35+
36+
// Work-around to init touch : interrupt pin must be set to low
37+
// Note: There is a resistor to 3V3 on interrupt pin which is blocking GT911 touch
38+
// See https://github.com/espressif/esp-bsp/blob/ad668c765cbad177495a122181df0a70ff9f8f61/bsp/m5stack_tab5/src/m5stack_tab5.c#L777
39+
tt::hal::gpio::configure(23, tt::hal::gpio::Mode::Output, true, false);
40+
tt::hal::gpio::setLevel(23, false);
41+
42+
auto configuration = std::make_shared<EspLcdConfiguration>(EspLcdConfiguration {
43+
.horizontalResolution = 720,
44+
.verticalResolution = 1280,
45+
.gapX = 0,
46+
.gapY = 0,
47+
.monochrome = false,
48+
.swapXY = false,
49+
.mirrorX = false,
50+
.mirrorY = false,
51+
.invertColor = false,
52+
.bufferSize = 0, // 0 = default (1/10 of screen)
53+
.touch = touch,
54+
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
55+
.resetPin = LCD_PIN_RESET,
56+
.lvglColorFormat = LV_COLOR_FORMAT_RGB565,
57+
.lvglSwapBytes = false,
58+
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_RGB,
59+
.bitsPerPixel = 16
60+
});
61+
62+
const auto display = std::make_shared<Ili9881cDisplay>(configuration);
63+
return std::static_pointer_cast<tt::hal::display::DisplayDevice>(display);
64+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#pragma once
2+
3+
#include <Tactility/hal/display/DisplayDevice.h>
4+
#include <memory>
5+
6+
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

0 commit comments

Comments
 (0)