Compare commits

...

10 Commits

Author SHA1 Message Date
Adolfo Reyna 5643ba5a2c Add ES3C35P board support 2026-07-24 20:32:19 -04:00
Adolfo Reyna 642847be41 fix(mcp): implement startMcpScreensaver - missing method caused linker error
- Was declared in DisplayIdleService.h but not defined in clean refactored branch
- Implementation taken from original 8970143f: locks LVGL, checks overlay, ensures backlight, creates McpScreensaver
- Fixes build of feature/local-all-rebased on es3c28p
2026-07-23 22:56:17 -04:00
Adolfo Reyna 0367b95f27 feat(app): allow external apps to hide statusbar via manifest flags
- Add parseAppFlagsString() in AppManifestParsing.cpp to parse comma-separated flags (HideStatusBar, Hidden, None)
- Parse [app]flags in V1 and app.flags in V2 manifests
- Loader already supports HideStatusBar, GuiService hides statusbarWidget when set
- Enables fullscreen for ELF apps (e.g. BibleVerse, BookPlayer) without firmware recompilation of internal manifests
- Add tests for flag parsing (38 tests passing)
- Tested on es3c28p /dev/cu.usbmodem1101 @ 192.168.68.133 with HelloWorld app
2026-07-23 22:56:17 -04:00
Adolfo Reyna 17773825fa fix(audio): ES8311 BOTH complementary open + audio-stream close ref-count + mic unmute
- es8311 driver open() now allows OUTPUT->INPUT complementary (promotes to BOTH) when same native rate 44100
- audio-stream close_stream() ref-counts shared BOTH codec (don't close if other direction still open)
- MCP recordVoice + VoiceRecorder app explicitly unmute and set 100% gain

Fixes mic input not working - was returning ERROR_RESOURCE when output already open
2026-07-23 22:56:17 -04:00
Adolfo Reyna 3115a685e2 fix(files): launch mp3 player from file explorer - audio support
- SupportedFiles: add isSupportedAudioFile (.mp3/.wav/.ogg/.flac)
- Files View::viewFile: if audio file, loader->start one.tactility.mp3player with file bundle
- Tactility.cpp: hide mcpoverride (screensaver internal), keep mcpsettings visible
- Fixes MP3 no longer running from file explorer, plus audio fast playback already fixed via audio-stream (Mp3Player/BookPlayer/VoiceRecorder use audio_stream_open_output not direct i2s_controller_write)
- MCP dev coexistence already fixed: DisplayIdle lock inversion 3629ffef, WebServer serverEnabled=ws||mcp, unauth /api/mcp, video 8081/8083 vs dev 6666
2026-07-23 22:56:17 -04:00
Adolfo Reyna ad4a15dce8 feat(mcp): restore MCP service with display charging toggle
- Restore MCP system (McpSystem 1900+ LOC, McpHandler, McpScreensaver, McpSettings, McpOverride apps)
- Use audio-stream instead of direct I2S for MP3 playback (fixes fast playback, uses native resampler)
- Register McpSettings + McpOverride in Tactility.cpp so Settings shows MCP Screen
- DisplaySettings: add ScreensaverType::McpScreen and disableScreensaverWhenCharging flag
- Display app: add 'Disable on charging' toggle, handles McpScreen screensaver type
- DisplayIdle: skip screensaver while charging, support McpScreen screensaver, isDeviceCharging check via PowerDevice
- WebServer: coexistence with MCP (McpHandler)
- Avoid formatting churn from previous commits

Squashed from range eaa248b0..8970143f (6 commits) into single clean commit
2026-07-23 22:56:17 -04:00
Ken Van Hoeylandt 29e80cfd65 T-Deck Max & Pro support updates (#582)
- Created kernel driver for T-Deck Max & Pro display (needs work, doesn't refresh reliably on T-Deck Pro)
- Created T-Deck Pro device implementation (incubating)
2026-07-24 00:17:48 +02:00
Ken Van Hoeylandt 429125734a Add drivers to module and make start/stop optional (#580) 2026-07-23 23:28:09 +02:00
Shadowtrance 08eac48e64 Fix Tab5 Display Issues (#579)
And add PPA rotation to lvgl_display
2026-07-22 23:58:34 +02:00
Ken Van Hoeylandt 8b92aa8e5a GPIO descriptor fixes (#578) 2026-07-22 22:43:34 +02:00
324 changed files with 9302 additions and 3983 deletions
+2 -7
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
struct Module btt_panda_touch_module = {
.name = "btt-panda-touch",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
Module btt_panda_touch_module = {
.name = "btt-panda-touch"
};
}
-5
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_2432s024c_module = {
.name = "cyd-2432s024c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
+2 -7
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
struct Module cyd_2432s024r_module = {
.name = "cyd-2432s024r",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
Module cyd_2432s024r_module = {
.name = "cyd-2432s024r"
};
}
+2 -7
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
struct Module cyd_2432s028r_module = {
.name = "cyd-2432s028r",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
Module cyd_2432s028r_module = {
.name = "cyd-2432s028r"
};
}
+2 -7
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
struct Module cyd_2432s028rv3_module = {
.name = "cyd-2432s028rv3",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
Module cyd_2432s028rv3_module = {
.name = "cyd-2432s028rv3"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_2432s032c_module = {
.name = "cyd-2432s032c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "cyd-2432s032c"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_3248s035c_module = {
.name = "cyd-3248s035c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "cyd-3248s035c"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_4848s040c_module = {
.name = "cyd-4848s040c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "cyd-4848s040c"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_8048s043c_module = {
.name = "cyd-8048s043c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "cyd-8048s043c"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_e32r28t_module = {
.name = "cyd-e32r28t",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "cyd-e32r28t"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_e32r32p_module = {
.name = "cyd-e32r32p",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "cyd-e32r32p"
};
}
@@ -1,13 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module elecrow_crowpanel_advance_28_module = {
.name = "elecrow-crowpanel-advance-28",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr
.name = "elecrow-crowpanel-advance-28"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module elecrow_crowpanel_advance_35_module = {
.name = "elecrow-crowpanel-advance-35",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "elecrow-crowpanel-advance-35"
};
}
@@ -86,9 +86,7 @@
vsync-back-porch = <8>;
vsync-front-porch = <8>;
pclk-active-neg;
num-fbs = <2>;
double-fb;
bounce-buffer-size-px = <8000>;
bounce-buffer-size-px = <4000>;
pin-hsync = <&gpio0 40 GPIO_FLAG_NONE>;
pin-vsync = <&gpio0 41 GPIO_FLAG_NONE>;
pin-de = <&gpio0 42 GPIO_FLAG_NONE>;
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module elecrow_crowpanel_advance_50_module = {
.name = "elecrow-crowpanel-advance-50",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "elecrow-crowpanel-advance-50"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module elecrow_crowpanel_basic_28_module = {
.name = "elecrow-crowpanel-basic-28",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "elecrow-crowpanel-basic-28"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module elecrow_crowpanel_basic_35_module = {
.name = "elecrow-crowpanel-basic-35",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "elecrow-crowpanel-basic-35"
};
}
@@ -89,9 +89,7 @@
vsync-back-porch = <12>;
vsync-front-porch = <8>;
pclk-active-neg;
num-fbs = <2>;
double-fb;
bounce-buffer-size-px = <8000>;
bounce-buffer-size-px = <4000>;
pin-hsync = <&gpio0 39 GPIO_FLAG_NONE>;
pin-vsync = <&gpio0 41 GPIO_FLAG_NONE>;
pin-de = <&gpio0 40 GPIO_FLAG_NONE>;
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module elecrow_crowpanel_basic_50_module = {
.name = "elecrow-crowpanel-basic-50",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "elecrow-crowpanel-basic-50"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module es3c28p_module = {
.name = "es3c28p",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "es3c28p"
};
}
+4
View File
@@ -0,0 +1,4 @@
idf_component_register(
SRCS "source/module.cpp"
REQUIRES TactilityKernel
)
+23
View File
@@ -0,0 +1,23 @@
general.vendor=LCDWIKI/Hosyond
general.name=ES3C35P
apps.launcherAppId=Launcher
hardware.target=ESP32S3
hardware.flashSize=16MB
hardware.spiRam=true
hardware.spiRamMode=OCT
hardware.spiRamSpeed=80M
hardware.esptoolFlashFreq=80M
hardware.tinyUsb=true
hardware.bluetooth=true
display.size=3.5"
display.shape=rectangle
display.dpi=165
lvgl.colorDepth=16
storage.userDataLocation=SD
dependencies.useDeprecatedHal=false
+6
View File
@@ -0,0 +1,6 @@
dependencies:
- Platforms/platform-esp32
- Drivers/st77922-module
- Drivers/es8311-module
- Drivers/audio-stream-module
dts: es3c35p.dts
+143
View File
@@ -0,0 +1,143 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_adc_oneshot.h>
#include <tactility/bindings/esp32_ble.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_i2s.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/esp32_sdmmc.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/battery_sense.h>
#include <tactility/bindings/gpio_hog.h>
#include <tactility/bindings/pwm_backlight.h>
#include <bindings/st77922.h>
#include <bindings/st77922_touch.h>
#include <bindings/es8311.h>
/ {
compatible = "root";
model = "LCDWIKI/Hosyond ES3C35P";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
ble0 {
compatible = "espressif,esp32-ble";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <49>;
};
/* FM8002E speaker amplifier enable, active-low on GPIO1. */
amp_enable {
compatible = "gpio-hog";
pin = <&gpio0 1 GPIO_FLAG_NONE>;
mode = <GPIO_HOG_MODE_OUTPUT_LOW>;
};
adc0 {
compatible = "espressif,esp32-adc-oneshot";
unit-id = <ADC_UNIT_1>;
clk-src = <ADC_RTC_CLK_SRC_DEFAULT>;
channels = <ADC_CHANNEL_7 ADC_ATTEN_DB_12 ADC_BITWIDTH_DEFAULT>;
};
/* BAT+ through a 200K/200K divider into GPIO8 / ADC1_CH7. */
battery-sense {
compatible = "battery-sense";
io-channel = <&adc0 0>;
reference-voltage-mv = <3300>;
multiplier = <2000>;
};
i2s0 {
compatible = "espressif,esp32-i2s";
port = <I2S_NUM_0>;
pin-bclk = <&gpio0 18 GPIO_FLAG_NONE>;
pin-ws = <&gpio0 21 GPIO_FLAG_NONE>;
pin-data-out = <&gpio0 15 GPIO_FLAG_NONE>;
pin-data-in = <&gpio0 16 GPIO_FLAG_NONE>;
pin-mclk = <&gpio0 17 GPIO_FLAG_NONE>;
};
i2c0 {
compatible = "espressif,esp32-i2c";
port = <I2C_NUM_0>;
clock-frequency = <400000>;
pin-sda = <&gpio0 38 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 39 GPIO_FLAG_NONE>;
touch@55 {
compatible = "sitronix,st77922-touch";
reg = <0x55>;
x-max = <320>;
y-max = <480>;
pin-reset = <&gpio0 48 GPIO_FLAG_NONE>;
pin-interrupt = <&gpio0 47 GPIO_FLAG_NONE>;
};
es8311: es8311@18 {
compatible = "everest,es8311";
reg = <0x18>;
i2s = <&i2s0>;
};
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 41 GPIO_FLAG_NONE>;
period-ns = <200000>;
ledc-timer = <0>;
ledc-channel = <0>;
};
display_backlight {
compatible = "pwm-backlight";
status = "disabled";
pwm = <&display_backlight_pwm>;
};
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-sclk = <&gpio0 12 GPIO_FLAG_NONE>;
pin-mosi = <&gpio0 11 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 13 GPIO_FLAG_NONE>;
pin-wp = <&gpio0 14 GPIO_FLAG_NONE>;
pin-hd = <&gpio0 9 GPIO_FLAG_NONE>;
cs-gpios = <&gpio0 10 GPIO_FLAG_NONE>;
/* Accommodate the driver's 1/10-frame DMA staging transfers, matching
* the vendor LVGL port's full-frame refresh path. */
max-transfer-size = <65536>;
display@0 {
compatible = "sitronix,st77922";
horizontal-resolution = <320>;
vertical-resolution = <480>;
/* 80 MHz works in the vendor demo, but produces visible QSPI corruption on
* some modules/cables. The component's 40 MHz default is reliably clean. */
pixel-clock-hz = <40000000>;
backlight = <&display_backlight>;
};
};
sdmmc0 {
compatible = "espressif,esp32-sdmmc";
pin-clk = <&gpio0 5 GPIO_FLAG_NONE>;
pin-cmd = <&gpio0 4 GPIO_FLAG_NONE>;
pin-d0 = <&gpio0 6 GPIO_FLAG_NONE>;
pin-d1 = <&gpio0 7 GPIO_FLAG_NONE>;
pin-d2 = <&gpio0 2 GPIO_FLAG_NONE>;
pin-d3 = <&gpio0 3 GPIO_FLAG_NONE>;
slot = <SDMMC_HOST_SLOT_1>;
bus-width = <4>;
};
};
+9
View File
@@ -0,0 +1,9 @@
#include <tactility/module.h>
extern "C" {
Module es3c35p_module = {
.name = "es3c35p"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module generic_esp32_module = {
.name = "generic-esp32",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "generic-esp32"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module generic_esp32c6_module = {
.name = "generic-esp32c6",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "generic-esp32c6"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module generic_esp32p4_module = {
.name = "generic-esp32p4",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "generic-esp32p4"
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module generic_esp32s3_module = {
.name = "generic-esp32s3",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "generic-esp32s3"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module guition_jc1060p470ciwy_module = {
.name = "guition-jc1060p470ciwy",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "guition-jc1060p470ciwy"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module guition_jc2432w328c_module = {
.name = "guition-jc2432w328c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "guition-jc2432w328c"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module guition_jc8048w550c_module = {
.name = "guition-jc8048w550c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "guition-jc8048w550c"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module heltec_wifi_lora_32_v3_module = {
.name = "heltec-wifi-lora-32-v3",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "heltec-wifi-lora-32-v3"
};
}
+1 -1
View File
@@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "source"
REQUIRES Tactility GDEQ031T10 driver
REQUIRES TactilityKernel
)
+8 -5
View File
@@ -1,6 +1,6 @@
general.vendor=LilyGO
general.name=T-Deck Max
# SD card support is not yet working; remove once it is functional.
# SD card support is not yet working, display driver is untested since refactoring; remove once it is functional.
general.incubating=true
apps.launcherAppId=Launcher
@@ -18,14 +18,17 @@ hardware.bluetooth=true
# Internal until the SD card is verified working on this board; switch to SD then.
storage.userDataLocation=Internal
dependencies.useDeprecatedHal=false
display.size=3.1"
display.shape=rectangle
display.dpi=128
# The GDEQ031T10 e-paper is monochrome, but its driver renders via
# LV_COLOR_FORMAT_I1 on its own display. The global LVGL color depth must stay
# at 16: esp_lvgl_port refuses to compile with LV_COLOR_DEPTH_1 set.
lvgl.colorDepth=16
lvgl.colorDepth=8
# Monochrome theme: the default colour theme renders accent-coloured UI that
# thresholds to invisible on a 1bpp panel (enables CONFIG_LV_USE_THEME_MONO).
lvgl.theme=Mono
cdn.warningMessage=Display not reliably working. Use at your own risk.
sdkconfig.CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME=0
+1
View File
@@ -2,6 +2,7 @@ dependencies:
- Platforms/platform-esp32
- Drivers/xl9555-module
- Drivers/cst66xx-module
- Drivers/gdeq031t10-module
- Drivers/tca8418-module
- Drivers/sy6970-module
- Drivers/bq27220-module
@@ -11,6 +11,7 @@
#include <tactility/bindings/pwm_backlight.h>
#include <bindings/xl9555.h>
#include <bindings/cst66xx.h>
#include <bindings/gdeq031t10.h>
#include <bindings/tca8418.h>
#include <bindings/sy6970.h>
#include <bindings/bq27220.h>
@@ -143,6 +144,17 @@
// exceeds the default ~4 KB transfer limit. Raise the bus limit to fit it.
max-transfer-size = <65536>;
display@0 {
compatible = "gooddisplay,gdeq031t10";
pin-dc = <&gpio0 35 GPIO_FLAG_NONE>;
pin-reset = <&gpio0 9 GPIO_FLAG_NONE>;
pin-busy = <&gpio0 37 GPIO_FLAG_NONE>;
clock-speed-hz = <10000000>;
// Default to a fast (~1s) refresh for the automatic ghost-clears so the
// full-screen flash they cause is as short as possible.
refresh-mode = <GDEQ031T10_REFRESH_FAST>;
};
sdcard@1 {
compatible = "espressif,esp32-sdspi";
status = "disabled";
@@ -1,35 +0,0 @@
#include "devices/Display.h"
#include <Tactility/hal/Configuration.h>
#include <tactility/check.h>
#include <tactility/device.h>
#include <tactility/drivers/esp32_spi.h>
using namespace tt::hal;
static bool initBoot() {
// The LoRa and SD chip-selects share the EPD's SPI bus but aren't wired up
// yet. spi0's start() already drives every cs-gpio high during kernel init;
// re-assert deselection before the EPD driver first transacts, as a cheap
// guard against either chip latching stray EPD command bytes (same pattern
// as the esp32_sdspi mount path).
auto* spi0 = device_find_by_name("spi0");
check(spi0 != nullptr);
esp32_spi_deselect_all_cs(spi0);
return true;
}
static DeviceVector createDevices() {
// Touch, keyboard and battery/charging are kernel drivers (cst66xx, tca8418, sy6970,
// bq27220 - see the .dts), started independently of this HAL layer. Only the EPD
// display remains on the deprecated HAL.
return DeviceVector {
createDisplay()
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,29 +0,0 @@
#include "Display.h"
#include <Gdeq031t10Display.h>
// Pins from Xinyuan-LilyGO/T-Deck-MAX's lib/TDeckMaxBoard/src/TDeckMaxBoard.h and docs/pinmap.md.
constexpr auto EPD_SPI_HOST = SPI2_HOST;
constexpr auto EPD_PIN_CS = GPIO_NUM_34;
constexpr auto EPD_PIN_DC = GPIO_NUM_35;
constexpr auto EPD_PIN_RST = GPIO_NUM_9;
constexpr auto EPD_PIN_BUSY = GPIO_NUM_37;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
// Touch is a kernel driver (hynitron,cst66xx - see the .dts), discovered and fed to LVGL
// independently of this display, so no touch device is passed into the configuration here.
auto configuration = std::make_unique<Gdeq031t10Display::Configuration>(
EPD_SPI_HOST,
EPD_PIN_CS,
EPD_PIN_DC,
EPD_PIN_RST,
EPD_PIN_BUSY,
nullptr,
10'000'000,
// Default to a fast (~1s) refresh for the automatic ghost-clears so the
// full-screen flash they cause is as short as possible.
Gdeq031t10Display::RefreshMode::Fast
);
return std::make_shared<Gdeq031t10Display>(std::move(configuration));
}
@@ -1,5 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
+2 -16
View File
@@ -2,22 +2,8 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module lilygo_tdeck_max_module = {
.name = "lilygo-tdeck-max",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
Module lilygo_tdeck_max_module = {
.name = "lilygo-tdeck-max"
};
}
@@ -12,6 +12,8 @@ hardware.tinyUsb=true
hardware.esptoolFlashFreq=120M
hardware.bluetooth=true
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD
display.size=2.8"
@@ -19,9 +19,6 @@
constexpr auto* TAG = "tdeck-plus";
// Legacy placeholder (required until legacy HAL is cleaned up everywhere)
extern const tt::hal::Configuration hardwareConfiguration = {};
extern "C" {
void subscribe_events() {
+7
View File
@@ -0,0 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "source"
REQUIRES TactilityKernel
)
@@ -0,0 +1,33 @@
general.vendor=LilyGO
general.name=T-Deck Pro
# The display driver is not reliable yet
general.incubating=true
apps.launcherAppId=Launcher
hardware.target=ESP32S3
hardware.flashSize=16MB
hardware.flashMode=DIO
hardware.spiRam=true
hardware.spiRamMode=AUTO
hardware.spiRamSpeed=80M
hardware.tinyUsb=true
hardware.esptoolFlashFreq=80M
hardware.bluetooth=true
storage.userDataLocation=SD
dependencies.useDeprecatedHal=false
display.size=3.1"
display.shape=rectangle
display.dpi=128
lvgl.colorDepth=8
# Monochrome theme: the default colour theme renders accent-coloured UI that
# thresholds to invisible on a 1bpp panel (enables CONFIG_LV_USE_THEME_MONO).
lvgl.theme=Mono
cdn.warningMessage=Only for hardware revision 1.0! Display not reliably working. Use at your own risk.
sdkconfig.CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME=0
+8
View File
@@ -0,0 +1,8 @@
dependencies:
- Platforms/platform-esp32
- Drivers/cst328-module
- Drivers/gdeq031t10-module
- Drivers/tca8418-module
- Drivers/sy6970-module
- Drivers/bq25896-module
dts: lilygo,tdeck-pro.dts
@@ -0,0 +1,138 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_ble.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c_master.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <bindings/cst328.h>
#include <bindings/gdeq031t10.h>
#include <bindings/tca8418.h>
#include <bindings/bq25896.h>
// Reference for V1.0 (not V1.1!): https://github.com/Xinyuan-LilyGO/T-Deck-Pro/tree/HD-V1-250326
// lib/TDeckMaxBoard/src/TDeckMaxBoard.h, docs/pinmap.md
/ {
compatible = "root";
model = "LilyGO T-Deck Pro";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
ble0 {
compatible = "espressif,esp32-ble";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <49>;
};
i2c0 {
compatible = "espressif,esp32-i2c-master";
port = <I2C_NUM_0>;
clock-frequency = <100000>;
pin-sda = <&gpio0 13 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 14 GPIO_FLAG_NONE>;
touch {
compatible = "hynitron,cst328";
reg = <0x1A>;
pin-reset = <&gpio0 45 GPIO_FLAG_NONE>;
};
// TCA8418 4x10 matrix scanner. Keymaps are written in the vendor's row/column
// orientation (Xinyuan-LilyGO/T-Deck-MAX examples/factory/peri_keypad.cpp); the
// TCA8418 columns are wired in reverse of that order, hence reverse-columns.
// ALT (shift/uppercase) is row 2 col 0; SYM (symbol layer) is row 3 col 8.
keyboard {
compatible = "ti,tca8418";
reg = <0x34>;
rows = <4>;
columns = <10>;
reverse-columns;
keymap-lc = [
113 119 101 114 116 121 117 105 111 112 // q w e r t y u i o p
97 115 100 102 103 104 106 107 108 8 // a s d f g h j k l BACKSPACE
0 122 120 99 118 98 110 109 36 10 // z x c v b n m $ ENTER
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
];
keymap-uc = [
81 87 69 82 84 89 85 73 79 80 // Q W E R T Y U I O P
65 83 68 70 71 72 74 75 76 8 // A S D F G H J K L BACKSPACE
0 90 88 67 86 66 78 77 36 10 // Z X C V B N M $ ENTER
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
];
keymap-sy = [
49 50 51 52 53 54 55 56 57 48 // 1 2 3 4 5 6 7 8 9 0
64 35 43 45 42 47 40 41 95 8 // @ # + - * / ( ) _ BACKSPACE
0 33 63 59 58 39 34 44 46 10 // ! ? ; : ' " , . ENTER
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
];
shift-row = <2>;
shift-col = <0>;
sym-row = <3>;
sym-col = <8>;
};
bq27220 {
compatible = "ti,bq25896";
reg = <0x6B>;
};
};
// Keyboard backlight (LED_PWM), GPIO42. The keypress-triggered flash/decay effect
// from the pre-migration driver isn't reproduced here - kernel drivers don't have a
// home for that kind of UI policy (same reasoning as the touch driver's dropped bezel
// keys). Off by default; app code can drive brightness via the generic pwm-backlight
// API if desired.
keyboard_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 42 GPIO_FLAG_NONE>;
period-ns = <33333>;
ledc-timer = <0>;
ledc-channel = <0>;
};
keyboard_backlight {
compatible = "pwm-backlight";
status = "disabled";
pwm = <&keyboard_backlight_pwm>;
};
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 34 GPIO_FLAG_NONE>, // 0: EPD display
<&gpio0 48 GPIO_FLAG_NONE>, // 1: SD card
<&gpio0 3 GPIO_FLAG_NONE>; // 2: LoRa radio (SX1262, not wired up yet)
pin-mosi = <&gpio0 33 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 47 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 36 GPIO_FLAG_NONE>;
// The EPD pushes its whole 9600-byte framebuffer in one SPI write, which
// exceeds the default ~4 KB transfer limit. Raise the bus limit to fit it.
max-transfer-size = <65536>;
display@0 {
compatible = "gooddisplay,gdeq031t10";
pin-dc = <&gpio0 35 GPIO_FLAG_NONE>;
pin-busy = <&gpio0 37 GPIO_FLAG_NONE>;
clock-speed-hz = <10000000>;
// Default to a fast (~1s) refresh for the automatic ghost-clears so the
// full-screen flash they cause is as short as possible.
refresh-mode = <GDEQ031T10_REFRESH_FAST>;
};
sdcard@1 {
compatible = "espressif,esp32-sdspi";
status = "disabled";
frequency-khz = <20000>;
};
};
};
@@ -0,0 +1,9 @@
#include <tactility/module.h>
extern "C" {
struct Module lilygo_tdeck_pro_module = {
.name = "lilygo-tdeck-pro"
};
}
+2
View File
@@ -12,6 +12,8 @@ hardware.tinyUsb=true
hardware.esptoolFlashFreq=120M
hardware.bluetooth=true
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD
display.size=2.8"
+1 -6
View File
@@ -18,9 +18,6 @@
constexpr auto* TAG = "tdeck";
// Legacy placeholder (required until legacy HAL is cleaned up everywhere)
extern const tt::hal::Configuration hardwareConfiguration = {};
extern "C" {
void subscribe_events() {
@@ -63,9 +60,7 @@ static error_t stop() {
Module lilygo_tdeck_module = {
.name = "lilygo-tdeck",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.stop = stop
};
}
+6 -5
View File
@@ -30,16 +30,17 @@ static error_t start() {
}
static error_t stop() {
// Empty for now
if (gpio_set_level(POWER_ON_PIN, 0) != ESP_OK) {
return ERROR_RESOURCE;
}
return ERROR_NONE;
}
struct Module lilygo_tdisplay_s3_module = {
Module lilygo_tdisplay_s3_module = {
.name = "lilygo-tdisplay-s3",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.stop = stop
};
}
+2 -16
View File
@@ -2,22 +2,8 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module lilygo_tdisplay_module = {
.name = "lilygo-tdisplay",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
Module lilygo_tdisplay_module = {
.name = "lilygo-tdisplay"
};
}
+2 -16
View File
@@ -2,22 +2,8 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module lilygo_tdongle_s3_module = {
.name = "lilygo-tdongle-s3",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
Module lilygo_tdongle_s3_module = {
.name = "lilygo-tdongle-s3"
};
}
+2 -16
View File
@@ -2,22 +2,8 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module lilygo_thmi_module = {
.name = "lilygo-thmi",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
Module lilygo_thmi_module = {
.name = "lilygo-thmi"
};
}
@@ -13,6 +13,8 @@ hardware.tinyUsb=true
hardware.esptoolFlashFreq=40M
hardware.bluetooth=true
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD
display.size=2.33"
+8 -16
View File
@@ -15,18 +15,15 @@
constexpr auto* TAG = "T-Lora Pager";
// Legacy placeholder (required until legacy HAL is cleaned up everywhere). All board
// peripherals are kernel drivers now (see the .dts): display (st7796), battery (bq27220),
// charger power-off (bq25896), haptics (drv2605), keyboard (tca8418) and the encoder wheel
// (lilygo,tpager-encoder, bound to LVGL below).
extern const tt::hal::Configuration hardwareConfiguration = {};
extern "C" {
static void subscribe_events() {
tt::kernel::SystemEventSubscription event_subscription;
static error_t start() {
LOG_I(TAG, LOG_MESSAGE_POWER_ON_START);
tt::kernel::subscribeSystemEvent(tt::kernel::SystemEvent::BootSplash, [](tt::kernel::SystemEvent) {
event_subscription = tt::kernel::subscribeSystemEvent(tt::kernel::SystemEvent::BootSplash, [](tt::kernel::SystemEvent) {
// The kernel tpager_encoder device is already started by kernel_init(); this just
// registers it as an LVGL input device, which requires LVGL to be up first.
lvgl_lock();
@@ -50,23 +47,18 @@ static void subscribe_events() {
}
}
});
}
static error_t start() {
subscribe_events();
return ERROR_NONE;
}
static error_t stop() {
tt::kernel::unsubscribeSystemEvent(event_subscription);
return ERROR_NONE;
}
struct Module lilygo_tlora_pager_module = {
Module lilygo_tlora_pager_module = {
.name = "lilygo-tlora-pager",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.stop = stop
};
}
@@ -2,22 +2,8 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module m5stack_cardputer_adv_module = {
.name = "m5stack-cardputer-adv",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
Module m5stack_cardputer_adv_module = {
.name = "m5stack-cardputer-adv"
};
}
+1 -15
View File
@@ -2,22 +2,8 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
Module m5stack_cardputer_module = {
.name = "m5stack-cardputer",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.name = "m5stack-cardputer"
};
}
+1 -6
View File
@@ -1,4 +1,3 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
@@ -7,11 +6,7 @@ extern "C" {
// and axp192-module's start()), replacing what used to be done by hand here via a
// DEVICE_EVENT_STARTED device_listener.
Module m5stack_core2_module = {
.name = "m5stack-core2",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "m5stack-core2"
};
}
@@ -205,5 +205,4 @@
backlight = <&display_backlight>;
};
};
};
+2 -9
View File
@@ -1,16 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
#include <cstring>
extern "C" {
struct Module m5stack_cores3_module = {
.name = "m5stack-cores3",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
Module m5stack_cores3_module = {
.name = "m5stack-cores3"
};
}
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: Apache-2.0
#include "papers3_power.h"
#include <tactility/check.h>
#include <tactility/driver.h>
#include <tactility/drivers/gpio.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/drivers/power_supply.h>
#include <tactility/drivers/pwm.h>
@@ -13,7 +15,7 @@
#include <new>
#define TAG "Papers3Power"
constexpr auto* TAG = "Papers3Power";
#define GET_CONFIG(device) (static_cast<const Papers3PowerConfig*>((device)->config))
// Power-off signal timing, ported from the old deprecated-HAL PaperS3Power::powerOff().
@@ -192,17 +194,8 @@ static void destroy_power_supply_child(Device* child) {
// region Driver lifecycle
static error_t acquire_input(const GpioPinSpec& pin, GpioDescriptor** out_descriptor) {
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
if (descriptor == nullptr) {
return ERROR_RESOURCE;
}
error_t error = gpio_descriptor_set_flags(descriptor, pin.flags | GPIO_FLAG_DIRECTION_INPUT);
if (error != ERROR_NONE) {
gpio_descriptor_release(descriptor);
return error;
}
*out_descriptor = descriptor;
return ERROR_NONE;
*out_descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, pin.flags | GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
return (*out_descriptor != nullptr) ? ERROR_NONE : ERROR_RESOURCE;
}
static error_t start(Device* device) {
@@ -226,13 +219,8 @@ static error_t start(Device* device) {
return ERROR_RESOURCE;
}
internal->power_off_descriptor = gpio_descriptor_acquire(config->pin_power_off.gpio_controller, config->pin_power_off.pin, GPIO_OWNER_GPIO);
if (internal->power_off_descriptor == nullptr ||
gpio_descriptor_set_flags(internal->power_off_descriptor, config->pin_power_off.flags | GPIO_FLAG_DIRECTION_OUTPUT) != ERROR_NONE) {
LOG_E(TAG, "Failed to configure power-off pin");
if (internal->power_off_descriptor != nullptr) {
gpio_descriptor_release(internal->power_off_descriptor);
}
internal->power_off_descriptor = gpio_descriptor_acquire(config->pin_power_off.gpio_controller, config->pin_power_off.pin, config->pin_power_off.flags | GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (internal->power_off_descriptor == nullptr) {
gpio_descriptor_release(internal->usb_detect_descriptor);
gpio_descriptor_release(internal->charge_status_descriptor);
delete internal;
+7 -19
View File
@@ -1,6 +1,4 @@
#include <tactility/check.h>
#include <tactility/driver.h>
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
@@ -9,26 +7,16 @@ extern Driver papers3_power_driver;
extern Driver papers3_power_supply_driver;
extern Driver papers3_display_driver;
static error_t start() {
check(driver_construct_add(&papers3_power_supply_driver) == ERROR_NONE);
check(driver_construct_add(&papers3_power_driver) == ERROR_NONE);
check(driver_construct_add(&papers3_display_driver) == ERROR_NONE);
return ERROR_NONE;
}
static error_t stop() {
check(driver_remove_destruct(&papers3_display_driver) == ERROR_NONE);
check(driver_remove_destruct(&papers3_power_driver) == ERROR_NONE);
check(driver_remove_destruct(&papers3_power_supply_driver) == ERROR_NONE);
return ERROR_NONE;
}
static Driver* const papers3_drivers[] = {
&papers3_display_driver,
&papers3_power_driver,
&papers3_power_supply_driver,
nullptr
};
Module m5stack_papers3_module = {
.name = "m5stack-papers3",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.drivers = papers3_drivers
};
}
@@ -7,8 +7,10 @@
#include <tactility/bindings/esp32_grove.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_i2s.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_uart.h>
#include <tactility/bindings/gpio_hog.h>
#include <bindings/aw88298.h>
#include <bindings/aw9523b.h>
#include <bindings/axp2101.h>
@@ -20,8 +22,6 @@
#include <bindings/ili9341.h>
#include <bindings/ina226.h>
#include <bindings/py32ioexpander.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/gpio_hog.h>
// Reference: https://docs.m5stack.com/en/StackChan
/ {
@@ -101,7 +101,7 @@
aw9523_sdcard_switch {
compatible = "gpio-hog";
pin = <&aw9523b 4 GPIO_FLAG_NONE>;
mode = <GPIO_HOG_MODE_OUTPUT_HIGH>;
mode = <GPIO_HOG_MODE_INPUT>;
};
aw9523_boost_enable {
+1 -3
View File
@@ -56,9 +56,7 @@ static error_t stop() {
Module m5stack_stackchan_module = {
.name = "m5stack-stackchan",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.stop = stop
};
}
+2 -15
View File
@@ -7,7 +7,7 @@ constexpr auto* TAG = "StickCPlus2";
extern "C" {
static bool init_power() {
static error_t init_power() {
// CH552 applies 4 V to GPIO 0, which reduces Wi-Fi sensitivity.
// Setting output to high adds a bias of 3.3 V and suppresses over-voltage:
gpio_set_direction(GPIO_NUM_0, GPIO_MODE_OUTPUT);
@@ -17,25 +17,12 @@ static bool init_power() {
gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
gpio_set_level(GPIO_NUM_4, 1);
return true;
}
static error_t start() {
init_power();
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
Module m5stack_stickc_plus2_module = {
.name = "m5stack-stickc-plus2",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.start = init_power
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module m5stack_sticks3_module = {
.name = "m5stack-sticks3",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "m5stack-sticks3"
};
}
@@ -36,14 +36,14 @@ static void apply_gt911_int_workaround() {
LOG_W(TAG, "display_detect: gpio0 not found, GT911 INT workaround not applied");
return;
}
auto* int_pin = gpio_descriptor_acquire(gpio0, 23, GPIO_OWNER_GPIO);
auto* int_pin = gpio_descriptor_acquire(gpio0, 23, GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
device_put(gpio0);
if (int_pin == nullptr) {
LOG_W(TAG, "display_detect: failed to acquire GPIO23 for GT911 INT workaround");
return;
}
gpio_descriptor_set_flags(int_pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_PULL_UP);
gpio_descriptor_set_level(int_pin, false);
gpio_descriptor_set_level(int_pin, true);
gpio_descriptor_release(int_pin);
}
@@ -67,8 +67,6 @@ static void create_gt911_touch(Device* i2c0) {
// Reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a direct SoC GPIO.
.pin_reset = GPIO_PIN_SPEC_NONE,
.pin_interrupt = GPIO_PIN_SPEC_NONE,
.reset_active_high = false,
.interrupt_active_high = false,
};
gt911_device.config = &gt911_config;
@@ -103,7 +101,6 @@ void tab5_create_devices_v1(Device* i2c0) {
// LCD reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a
// direct SoC GPIO.
.pin_reset = GPIO_PIN_SPEC_NONE,
.reset_active_high = false,
.ldo_channel = 3,
.ldo_voltage_mv = 2500,
.dsi_bus_id = 0,
@@ -116,10 +113,10 @@ void tab5_create_devices_v1(Device* i2c0) {
.vsync_pulse_width = 4,
.vsync_back_porch = 20,
.vsync_front_porch = 20,
.num_fbs = 1,
.use_dma2d = false,
.num_fbs = 2,
.use_dma2d = true,
.disable_lp = false,
.allow_tearing = true, // matches old lvgl_port_display_dsi_cfg_t.avoid_tearing = 0
.allow_tearing = true, // matches old lvgl_port_display_dsi_cfg_t.avoid_tearing = 0 (disabled = don't wait)
.init_sequence = display_init_bytes.data(),
.init_sequence_length = (uint32_t)display_init_bytes.size(),
.backlight = backlight,
@@ -50,8 +50,6 @@ static void create_st7123_touch(Device* i2c0) {
// Reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a direct SoC GPIO.
.pin_reset = GPIO_PIN_SPEC_NONE,
.pin_interrupt = pin_interrupt,
.reset_active_high = false,
.interrupt_active_high = false,
};
st7123_touch_device.config = &st7123_touch_config;
@@ -82,7 +80,6 @@ void tab5_create_devices_v2(Device* i2c0) {
.mirror_x = false,
.mirror_y = false,
.pin_reset = GPIO_PIN_SPEC_NONE,
.reset_active_high = false,
.ldo_channel = 3,
.ldo_voltage_mv = 2500,
.dsi_bus_id = 0,
@@ -95,10 +92,10 @@ void tab5_create_devices_v2(Device* i2c0) {
.vsync_pulse_width = 2,
.vsync_back_porch = 8,
.vsync_front_porch = 220,
.num_fbs = 1,
.use_dma2d = false,
.num_fbs = 2,
.use_dma2d = true,
.disable_lp = false,
.allow_tearing = true,
.allow_tearing = true, // matches old lvgl_port_display_dsi_cfg_t.avoid_tearing = 0 (disabled = don't wait)
.init_sequence = display_init_bytes.data(),
.init_sequence_length = (uint32_t)display_init_bytes.size(),
.backlight = backlight,
@@ -1,6 +1,5 @@
#include "detect.h"
#include "../../../../TactilityKernel/include/tactility/log.h"
#include "devices_common.h"
#include "devices_v1.h"
#include "devices_v2.h"
@@ -8,6 +7,7 @@
#include <tactility/device.h>
#include <tactility/device_listener.h>
#include <tactility/drivers/gpio.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/log.h>
@@ -36,8 +36,8 @@ constexpr auto GPIO_EXP0_PIN_LCD_RESET = 4;
constexpr auto GPIO_EXP0_PIN_TOUCH_RESET = 5;
bool pulse_display_reset_pins(Device* io_expander0) {
auto* lcd_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_LCD_RESET, GPIO_OWNER_GPIO);
auto* touch_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_TOUCH_RESET, GPIO_OWNER_GPIO);
auto* lcd_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_LCD_RESET, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
auto* touch_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_TOUCH_RESET, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
if (lcd_reset_pin == nullptr || touch_reset_pin == nullptr) {
LOG_E(TAG, "display_detect: failed to acquire LCD/touch reset pins on io_expander0");
if (lcd_reset_pin != nullptr) {
@@ -51,11 +51,11 @@ bool pulse_display_reset_pins(Device* io_expander0) {
gpio_descriptor_set_flags(lcd_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_flags(touch_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(lcd_reset_pin, false);
gpio_descriptor_set_level(touch_reset_pin, false);
vTaskDelay(pdMS_TO_TICKS(10));
gpio_descriptor_set_level(lcd_reset_pin, true);
gpio_descriptor_set_level(touch_reset_pin, true);
vTaskDelay(pdMS_TO_TICKS(10));
gpio_descriptor_set_level(lcd_reset_pin, false);
gpio_descriptor_set_level(touch_reset_pin, false);
gpio_descriptor_release(lcd_reset_pin);
gpio_descriptor_release(touch_reset_pin);
@@ -1,6 +1,7 @@
#include "tab5_headphone_detect.h"
#include <tactility/device.h>
#include <tactility/drivers/gpio.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/log.h>
@@ -35,7 +36,7 @@ static void headphone_detect_callback(TimerHandle_t /*timer*/) {
return; // Not ready yet, will retry on next tick
}
auto* hp_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_OWNER_GPIO);
auto* hp_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
if (!hp_pin) {
LOG_W(TAG, "hp_detect: HP_DET pin busy");
return;
@@ -53,7 +54,7 @@ static void headphone_detect_callback(TimerHandle_t /*timer*/) {
LOG_D(TAG, "hp_detect: HP_DET=%d", (int)hp);
if (!hp_detect_initialized || hp != hp_detect_last) {
auto* spk_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
auto* spk_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (!spk_pin) {
LOG_W(TAG, "hp_detect: SPK_EN pin busy, will retry");
return;
@@ -3,6 +3,7 @@
#include <tactility/device.h>
#include <tactility/driver.h>
#include <tactility/drivers/gpio.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/drivers/power_supply.h>
#include <tactility/log.h>
@@ -51,15 +52,12 @@ static error_t ps_set_allowed_to_charge(Device* device, bool allowed) {
auto* internal = static_cast<Tab5PowerControlInternal*>(device_get_driver_data(device));
auto* io_expander1 = device_get_parent(device);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_EN, GPIO_OWNER_GPIO);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_EN, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (pin == nullptr) {
LOG_W(TAG, "Failed to acquire CHG_EN pin");
return ERROR_RESOURCE;
}
error_t error = gpio_descriptor_set_flags(pin, GPIO_FLAG_DIRECTION_OUTPUT);
if (error == ERROR_NONE) {
error = gpio_descriptor_set_level(pin, allowed);
}
auto error = gpio_descriptor_set_level(pin, allowed);
gpio_descriptor_release(pin);
if (error != ERROR_NONE) {
LOG_W(TAG, "Failed to set CHG_EN pin");
@@ -83,15 +81,12 @@ static error_t ps_set_quick_charge_enabled(Device* device, bool enabled) {
auto* internal = static_cast<Tab5PowerControlInternal*>(device_get_driver_data(device));
auto* io_expander1 = device_get_parent(device);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_NCHG_QC_EN, GPIO_OWNER_GPIO);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_NCHG_QC_EN, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (pin == nullptr) {
LOG_W(TAG, "Failed to acquire nCHG_QC_EN pin");
return ERROR_RESOURCE;
}
error_t error = gpio_descriptor_set_flags(pin, GPIO_FLAG_DIRECTION_OUTPUT);
if (error == ERROR_NONE) {
error = gpio_descriptor_set_level(pin, !enabled); // active-low
}
auto error = gpio_descriptor_set_level(pin, !enabled); // active-low
gpio_descriptor_release(pin);
if (error != ERROR_NONE) {
LOG_W(TAG, "Failed to set nCHG_QC_EN pin");
@@ -108,7 +103,7 @@ static bool ps_supports_power_off(Device*) {
static error_t ps_power_off(Device* device) {
auto* io_expander1 = device_get_parent(device);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_OWNER_GPIO);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (pin == nullptr) {
LOG_E(TAG, "Failed to acquire DEVICE_POWER pin");
return ERROR_RESOURCE;
@@ -153,9 +148,8 @@ static error_t start(Device* device) {
// as an idle-low output up front so it's in a known state (previously done by Configuration.cpp's
// initExpander1(), now owned here - see that function's comment for why it no longer touches it).
auto* io_expander1 = device_get_parent(device);
auto* device_power_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_OWNER_GPIO);
auto* device_power_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (device_power_pin != nullptr) {
gpio_descriptor_set_flags(device_power_pin, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(device_power_pin, false);
gpio_descriptor_release(device_power_pin);
} else {
+12 -27
View File
@@ -1,4 +1,5 @@
#include <tactility/module.h>
#include <tactility/check.h>
#include <tactility/device.h>
#include <tactility/device_listener.h>
@@ -15,7 +16,7 @@
#include "devices/tab5_power_control.h"
#include "devices/tab_5_camera.h"
#define TAG "Tab5"
constexpr auto* TAG = "Tab5";
// PI4IOE5V6408-0 (0x43) bit 1
constexpr auto GPIO_EXP0_PIN_SPEAKER_ENABLE = 1;
@@ -25,14 +26,11 @@ constexpr auto GPIO_EXP0_PIN_HEADPHONE_DETECT = 7;
static void tab5_init_expander0(Device* io_expander0) {
// Speaker and heapdhone pins are managed at runtime, so we can't have them as a hog in the dts file
// We have to init them manually.
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
check(speaker_enable_pin);
auto* headphone_detect_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_OWNER_GPIO);
auto* headphone_detect_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
check(headphone_detect_pin);
gpio_descriptor_set_flags(speaker_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_flags(headphone_detect_pin, GPIO_FLAG_DIRECTION_INPUT);
gpio_descriptor_set_level(speaker_enable_pin, false);
gpio_descriptor_release(speaker_enable_pin);
@@ -40,7 +38,7 @@ static void tab5_init_expander0(Device* io_expander0) {
}
static void tab5_enable_speaker_amp(Device* io_expander0) {
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
check(speaker_enable_pin, "Failed to acquire speaker enable pin");
error_t error = gpio_descriptor_set_level(speaker_enable_pin, true);
gpio_descriptor_release(speaker_enable_pin);
@@ -67,44 +65,31 @@ static void on_io_expander0_started(Device* device, DeviceEvent event, void* con
extern "C" {
static error_t start() {
/* Crash when construct fails, because if a single driver fails to construct,
* there is no guarantee that the previously constructed drivers can be destroyed */
check(driver_construct_add(&tab5_keyboard_driver) == ERROR_NONE);
check(driver_construct_add(&tab5_power_control_driver) == ERROR_NONE);
tab5_detect_start();
tab5_camera_init();
device_listener_add(on_io_expander0_started, nullptr);
tab5_headphone_detect_start();
return ERROR_NONE;
}
static error_t stop() {
tab5_headphone_detect_stop();
device_listener_remove(on_io_expander0_started);
tab5_detect_stop();
/* Crash when destruct fails, because if a single driver fails to destruct,
* there is no guarantee that the previously destroyed drivers can be recovered */
check(driver_remove_destruct(&tab5_keyboard_driver) == ERROR_NONE);
check(driver_remove_destruct(&tab5_power_control_driver) == ERROR_NONE);
return ERROR_NONE;
}
static Driver* const tab5_drivers[] = {
&tab5_keyboard_driver,
&tab5_power_control_driver,
nullptr
};
Module m5stack_tab5_module = {
.name = "m5stack-tab5",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.drivers = tab5_drivers
};
}
+1 -2
View File
@@ -46,8 +46,7 @@ sdkconfig.CONFIG_ESP_HOSTED_ENABLE_PEER_DATA_TRANSFER=y
sdkconfig.CONFIG_ESP_HOSTED_MAX_CUSTOM_MSG_HANDLERS=8
# Performance: larger L2 cache reduces PSRAM stalls for draw/DPI buffers
sdkconfig.CONFIG_CACHE_L2_CACHE_256KB=y
# Performance: use P4's PPA (pixel processing accelerator for rotation)
sdkconfig.CONFIG_LVGL_PORT_ENABLE_PPA=y
# Performance: cache-line-aligned draw buffers, required for PPA/DMA2D coherency (see lvgl-module's lvgl_display_alloc_buffer())
sdkconfig.CONFIG_LV_DRAW_BUF_ALIGN=64
sdkconfig.CONFIG_LV_DEF_REFR_PERIOD=15
# SC202CS (SC2356) MIPI CSI camera sensor + ISP pipeline (AE/AWB/demosaicing)
+1 -3
View File
@@ -21,10 +21,8 @@ bool BatteryManager::initGpioExpander() {
return false;
}
expanderPowerPin = gpio_descriptor_acquire(expander, expanderpin::EXPANDER_POWER, GPIO_OWNER_GPIO);
expanderPowerPin = gpio_descriptor_acquire(expander, expanderpin::EXPANDER_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
check(expanderPowerPin != nullptr);
gpio_descriptor_set_flags(expanderPowerPin, GPIO_FLAG_DIRECTION_OUTPUT);
device_put(expander);
return true;
@@ -90,21 +90,19 @@ static int32_t nav_buttons_thread_main(UnphoneNavButtonsInternal* internal) {
// region Pin acquisition
static error_t acquire_button(const GpioPinSpec& pin, void (*callback)(void*), void* arg, GpioDescriptor** out_descriptor) {
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
if (descriptor == nullptr) {
return ERROR_RESOURCE;
}
// Digital pull-up; the buttons pull the pin low while pressed. Listen for the release
// (positive edge) rather than the press - if we listen to the press, these buttons can
// generate more than one signal when held down (mirrors the original unPhone init).
gpio_flags_t flags = GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP;
flags = GPIO_FLAG_INTERRUPT_TO_OPTIONS(flags, GPIO_INTERRUPT_POS_EDGE);
error_t error = gpio_descriptor_set_flags(descriptor, flags);
if (error == ERROR_NONE) {
error = gpio_descriptor_add_callback(descriptor, callback, arg);
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, flags, GPIO_OWNER_GPIO);
if (descriptor == nullptr) {
return ERROR_RESOURCE;
}
auto error = gpio_descriptor_add_callback(descriptor, callback, arg);
if (error == ERROR_NONE) {
error = gpio_descriptor_enable_interrupt(descriptor);
}
@@ -25,18 +25,12 @@ extern Module unphone_module;
static error_t start(Device* device) {
const auto* config = GET_CONFIG(device);
auto* descriptor = gpio_descriptor_acquire(config->pin.gpio_controller, config->pin.pin, GPIO_OWNER_GPIO);
auto* descriptor = gpio_descriptor_acquire(config->pin.gpio_controller, config->pin.pin, config->pin.flags | GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
if (descriptor == nullptr) {
LOG_E(TAG, "Failed to acquire GPIO descriptor");
return ERROR_RESOURCE;
}
if (gpio_descriptor_set_flags(descriptor, config->pin.flags | GPIO_FLAG_DIRECTION_INPUT) != ERROR_NONE) {
LOG_E(TAG, "Failed to configure power switch pin as input");
gpio_descriptor_release(descriptor);
return ERROR_RESOURCE;
}
gpio_num_t native_pin;
if (gpio_descriptor_get_native_pin_number(descriptor, &native_pin) != ERROR_NONE) {
LOG_E(TAG, "Power switch pin has no native pin number");
+8 -11
View File
@@ -38,29 +38,26 @@ static void on_device_event(Device* device, DeviceEvent event, void* context) {
}
static error_t start() {
/* We crash when construct fails, because if a single driver fails to construct,
* there is no guarantee that the previously constructed drivers can be destroyed */
check(driver_construct_add(&unphone_power_switch_driver) == ERROR_NONE);
check(driver_construct_add(&unphone_nav_buttons_driver) == ERROR_NONE);
device_listener_add(on_device_event, nullptr);
return ERROR_NONE;
}
static error_t stop() {
device_listener_remove(&on_device_event);
/* We crash when destruct fails, because if a single driver fails to destruct,
* there is no guarantee that the previously destroyed drivers can be recovered */
check(driver_remove_destruct(&unphone_nav_buttons_driver) == ERROR_NONE);
check(driver_remove_destruct(&unphone_power_switch_driver) == ERROR_NONE);
return ERROR_NONE;
}
struct Module unphone_module = {
static Driver* const unphone_drivers[] = {
&unphone_nav_buttons_driver,
&unphone_power_switch_driver,
nullptr
};
Module unphone_module = {
.name = "unphone",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
.drivers = unphone_drivers
};
}
@@ -2,22 +2,8 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module waveshare_esp32_s3_geek_module = {
.name = "waveshare-esp32-s3-geek",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
Module waveshare_esp32_s3_geek_module = {
.name = "waveshare-esp32-s3-geek"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module waveshare_s3_lcd_13_module = {
.name = "waveshare-s3-lcd-13",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "waveshare-s3-lcd-13"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module waveshare_s3_touch_lcd_128_module = {
.name = "waveshare-s3-touch-lcd-128",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "waveshare-s3-touch-lcd-128"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module waveshare_s3_touch_lcd_147_module = {
.name = "waveshare-s3-touch-lcd-147",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "waveshare-s3-touch-lcd-147"
};
}
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module waveshare_s3_touch_lcd_43_module = {
.name = "waveshare-s3-touch-lcd-43",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "waveshare-s3-touch-lcd-43"
};
}
@@ -96,9 +96,8 @@
vsync-back-porch = <8>;
vsync-front-porch = <8>;
pclk-active-neg;
num-fbs = <2>;
double-fb;
bounce-buffer-size-px = <8000>;
num-fbs = <1>;
bounce-buffer-size-px = <4000>;
pin-hsync = <&gpio0 46 GPIO_FLAG_NONE>;
pin-vsync = <&gpio0 3 GPIO_FLAG_NONE>;
pin-de = <&gpio0 5 GPIO_FLAG_NONE>;
@@ -1,14 +1,9 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module wireless_tag_wt32_sc01_plus_module = {
.name = "wireless-tag-wt32-sc01-plus",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
.name = "wireless-tag-wt32-sc01-plus"
};
}
+3
View File
@@ -13,6 +13,9 @@
## Higher Priority
- Drivers/audio-codec-module is not a module. Move it somewhere else. Or make it an actual module.
- LilyGO T-Dongle S3: 1 button control, stop auto-launching web server
- Core2: support power off via software
- Create `#define` for empty module (for modules that fully rely on device.properties and don't define drivers or have start/stop logic)
- Get rid of TactilityC in favour of TactilityKernel and kernel modules
- Improve SPI kernel driver (implement read, write, transactions)
-5
View File
@@ -1,5 +0,0 @@
idf_component_register(
SRC_DIRS "Source"
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lcd esp_lcd_touch esp_lvgl_port
)
-3
View File
@@ -1,3 +0,0 @@
# EspLcdCompat
A set of helper classes to implement `esp_lcd` drivers in Tactility.
@@ -1,130 +0,0 @@
#include "EspLcdDisplay.h"
#include "EspLcdDisplayDriver.h"
#include <tactility/log.h>
#include <tactility/check.h>
#include <Tactility/hal/touch/TouchDevice.h>
#include <cassert>
#include <esp_lvgl_port_disp.h>
constexpr auto* TAG = "EspLcdDisplay";
EspLcdDisplay::~EspLcdDisplay() {
check(
displayDriver == nullptr || displayDriver.use_count() < 2, // 1 reference is held by this class
"DisplayDriver is still in use. This will cause memory access violations."
);
}
bool EspLcdDisplay::start() {
if (!createIoHandle(ioHandle)) {
LOG_E(TAG, "Failed to create IO handle");
return false;
}
if (!createPanelHandle(ioHandle, panelHandle)) {
LOG_E(TAG, "Failed to create panel handle");
esp_lcd_panel_io_del(ioHandle);
return false;
}
return true;
}
bool EspLcdDisplay::stop() {
if (lvglDisplay != nullptr) {
stopLvgl();
lvglDisplay = nullptr;
}
if (panelHandle != nullptr && esp_lcd_panel_del(panelHandle) != ESP_OK) {
return false;
}
if (ioHandle != nullptr && esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
return false;
}
if (displayDriver != nullptr && displayDriver.use_count() > 1) {
LOG_W(TAG, "DisplayDriver is still in use.");
}
return true;
}
bool EspLcdDisplay::startLvgl() {
assert(lvglDisplay == nullptr);
if (displayDriver != nullptr && displayDriver.use_count() > 1) {
LOG_W(TAG, "DisplayDriver is still in use.");
}
auto lvgl_port_config = getLvglPortDisplayConfig(ioHandle, panelHandle);
if (isRgbPanel()) {
auto rgb_config = getLvglPortDisplayRgbConfig(ioHandle, panelHandle);
lvglDisplay = lvgl_port_add_disp_rgb(&lvgl_port_config , &rgb_config);
} else {
lvglDisplay = lvgl_port_add_disp(&lvgl_port_config );
}
auto touch_device = getTouchDevice();
if (touch_device != nullptr && touch_device->supportsLvgl()) {
touch_device->startLvgl(lvglDisplay);
}
return lvglDisplay != nullptr;
}
bool EspLcdDisplay::stopLvgl() {
if (lvglDisplay == nullptr) {
return false;
}
auto touch_device = getTouchDevice();
if (touch_device != nullptr) {
touch_device->stopLvgl();
}
lvgl_port_remove_disp(lvglDisplay);
lvglDisplay = nullptr;
return true;
}
std::shared_ptr<tt::hal::display::DisplayDriver> EspLcdDisplay::getDisplayDriver() {
assert(lvglDisplay == nullptr); // Still attached to LVGL context. Call stopLvgl() first.
if (displayDriver == nullptr) {
auto lvgl_port_config = getLvglPortDisplayConfig(ioHandle, panelHandle);
tt::hal::display::ColorFormat color_format;
if (lvgl_port_config.color_format == LV_COLOR_FORMAT_I1) {
color_format = tt::hal::display::ColorFormat::Monochrome;
} else if (lvgl_port_config.color_format == LV_COLOR_FORMAT_RGB565) {
if (rgbElementOrder == LCD_RGB_ELEMENT_ORDER_RGB) {
if (lvgl_port_config.flags.swap_bytes) {
color_format = tt::hal::display::ColorFormat::RGB565Swapped;
} else {
color_format = tt::hal::display::ColorFormat::RGB565;
}
} else {
if (lvgl_port_config.flags.swap_bytes) {
color_format = tt::hal::display::ColorFormat::BGR565Swapped;
} else {
color_format = tt::hal::display::ColorFormat::BGR565;
}
}
} else if (lvgl_port_config.color_format == LV_COLOR_FORMAT_RGB888) {
color_format = tt::hal::display::ColorFormat::RGB888;
} else {
check(false, "unsupported driver");
}
displayDriver = std::make_shared<EspLcdDisplayDriver>(
panelHandle,
lvgl_port_config.hres,
lvgl_port_config.vres,
color_format
);
}
return displayDriver;
}
@@ -1,64 +0,0 @@
#pragma once
#include <tactility/check.h>
#include <Tactility/hal/display/DisplayDevice.h>
#include <esp_lcd_types.h>
#include <esp_lvgl_port_disp.h>
/** @deprecated use EspLcdDisplayV2 */
class EspLcdDisplay : public tt::hal::display::DisplayDevice {
esp_lcd_panel_io_handle_t ioHandle = nullptr;
esp_lcd_panel_handle_t panelHandle = nullptr;
lv_display_t* lvglDisplay = nullptr;
std::shared_ptr<tt::hal::display::DisplayDriver> displayDriver;
/** @warning This is never changed, so a driver that needs BGR is not supported */
lcd_rgb_element_order_t rgbElementOrder = LCD_RGB_ELEMENT_ORDER_RGB;
protected:
// Used for sending commands such as setting curves
esp_lcd_panel_io_handle_t getIoHandle() const { return ioHandle; }
virtual bool createIoHandle(esp_lcd_panel_io_handle_t& outHandle) = 0;
virtual bool createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t& panelHandle) = 0;
virtual lvgl_port_display_cfg_t getLvglPortDisplayConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) = 0;
virtual bool isRgbPanel() const { return false; }
virtual lvgl_port_display_rgb_cfg_t getLvglPortDisplayRgbConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) { check(false, "Not supported"); }
public:
EspLcdDisplay() = default;
~EspLcdDisplay() override;
bool start() final;
bool stop() final;
// region LVGL
bool supportsLvgl() const final { return true; }
bool startLvgl() final;
bool stopLvgl() final;
lv_display_t* getLvglDisplay() const final { return lvglDisplay; }
// endregion
// region DisplayDriver
bool supportsDisplayDriver() const override { return true; }
/** @return a NativeDisplay instance if this device supports it */
std::shared_ptr<tt::hal::display::DisplayDriver> getDisplayDriver() final;
// endregion
};
@@ -1,47 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDriver.h>
#include <esp_lcd_panel_ops.h>
#if CONFIG_SOC_MIPI_DSI_SUPPORTED
#include <esp_lcd_mipi_dsi.h>
#endif
class EspLcdDisplayDriver : public tt::hal::display::DisplayDriver {
esp_lcd_panel_handle_t panelHandle;
uint16_t hRes;
uint16_t vRes;
tt::hal::display::ColorFormat colorFormat;
public:
EspLcdDisplayDriver(
esp_lcd_panel_handle_t panelHandle,
uint16_t hRes,
uint16_t vRes,
tt::hal::display::ColorFormat colorFormat
) : panelHandle(panelHandle), hRes(hRes), vRes(vRes), colorFormat(colorFormat) {}
tt::hal::display::ColorFormat getColorFormat() const override {
return colorFormat;
}
bool drawBitmap(int xStart, int yStart, int xEnd, int yEnd, const void* pixelData) override {
bool result = esp_lcd_panel_draw_bitmap(panelHandle, xStart, yStart, xEnd, yEnd, pixelData) == ESP_OK;
return result;
}
uint16_t getPixelWidth() const override { return hRes; }
uint16_t getPixelHeight() const override { return vRes; }
#if CONFIG_SOC_MIPI_DSI_SUPPORTED
uint8_t getFrameBuffers(void* outBuffers[2]) const override {
if (outBuffers == nullptr) {
return 0;
}
return (esp_lcd_dpi_panel_get_frame_buffer(panelHandle, 2, &outBuffers[0], &outBuffers[1]) == ESP_OK) ? 2 : 0;
}
#endif
};
@@ -1,231 +0,0 @@
#include "EspLcdDisplayV2.h"
#include "EspLcdDisplayDriver.h"
#include <tactility/log.h>
#include <tactility/check.h>
#include <Tactility/hal/touch/TouchDevice.h>
#include <cassert>
#include <esp_lvgl_port_disp.h>
constexpr auto* TAG = "EspLcdDispV2";
inline unsigned int getBufferSize(const std::shared_ptr<EspLcdConfiguration>& configuration) {
if (configuration->bufferSize != DEFAULT_BUFFER_SIZE) {
return configuration->bufferSize;
} else {
return configuration->horizontalResolution * (configuration->verticalResolution / 10);
}
}
EspLcdDisplayV2::~EspLcdDisplayV2() {
check(
displayDriver == nullptr || displayDriver.use_count() < 2, // 1 reference is held by this class
"DisplayDriver is still in use. This will cause memory access violations."
);
}
bool EspLcdDisplayV2::applyConfiguration() const {
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
LOG_E(TAG, "Failed to reset panel");
return false;
}
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
LOG_E(TAG, "Failed to init panel");
return false;
}
if (configuration->invertColor && esp_lcd_panel_invert_color(panelHandle, configuration->invertColor) != ESP_OK) {
LOG_E(TAG, "Failed to set panel to invert");
return false;
}
// Warning: it looks like LVGL rotation is broken when "gap" is set and the screen is moved to a non-default orientation
int gap_x = configuration->swapXY ? configuration->gapY : configuration->gapX;
int gap_y = configuration->swapXY ? configuration->gapX : configuration->gapY;
bool should_set_gap = gap_x != 0 || gap_y != 0;
if (should_set_gap && esp_lcd_panel_set_gap(panelHandle, gap_x, gap_y) != ESP_OK) {
LOG_E(TAG, "Failed to set panel gap");
return false;
}
if (configuration->swapXY && esp_lcd_panel_swap_xy(panelHandle, configuration->swapXY) != ESP_OK) {
LOG_E(TAG, "Failed to swap XY ");
return false;
}
bool should_set_mirror = configuration->mirrorX || configuration->mirrorY;
if (should_set_mirror && esp_lcd_panel_mirror(panelHandle, configuration->mirrorX, configuration->mirrorY) != ESP_OK) {
LOG_E(TAG, "Failed to set panel to mirror");
return false;
}
if (configuration->invertColor && esp_lcd_panel_invert_color(panelHandle, configuration->invertColor) != ESP_OK) {
LOG_E(TAG, "Failed to set panel to invert");
return false;
}
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
LOG_E(TAG, "Failed to turn display on");
return false;
}
return true;
}
bool EspLcdDisplayV2::start() {
if (!createIoHandle(ioHandle)) {
LOG_E(TAG, "Failed to create IO handle");
return false;
}
esp_lcd_panel_dev_config_t panel_config = createPanelConfig(configuration, configuration->resetPin);
if (!createPanelHandle(ioHandle, panel_config, panelHandle)) {
LOG_E(TAG, "Failed to create panel handle");
esp_lcd_panel_io_del(ioHandle);
ioHandle = nullptr;
return false;
}
if (!applyConfiguration()) {
esp_lcd_panel_del(panelHandle);
panelHandle = nullptr;
esp_lcd_panel_io_del(ioHandle);
ioHandle = nullptr;
return false;
}
return true;
}
bool EspLcdDisplayV2::stop() {
if (lvglDisplay != nullptr) {
stopLvgl();
lvglDisplay = nullptr;
}
if (panelHandle != nullptr && esp_lcd_panel_del(panelHandle) != ESP_OK) {
return false;
}
if (ioHandle != nullptr && esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
return false;
}
if (displayDriver != nullptr && displayDriver.use_count() > 1) {
LOG_W(TAG, "DisplayDriver is still in use.");
}
return true;
}
bool EspLcdDisplayV2::startLvgl() {
assert(lvglDisplay == nullptr);
if (displayDriver != nullptr && displayDriver.use_count() > 1) {
LOG_W(TAG, "DisplayDriver is still in use.");
}
auto lvgl_port_config = getLvglPortDisplayConfig(configuration, ioHandle, panelHandle);
if (useDsiPanel()) {
auto dsi_config = getLvglPortDisplayDsiConfig(ioHandle, panelHandle);
lvglDisplay = lvgl_port_add_disp_dsi(&lvgl_port_config, &dsi_config);
} else if (isRgbPanel()) {
auto rgb_config = getLvglPortDisplayRgbConfig(ioHandle, panelHandle);
lvglDisplay = lvgl_port_add_disp_rgb(&lvgl_port_config, &rgb_config);
} else {
lvglDisplay = lvgl_port_add_disp(&lvgl_port_config);
}
auto touch_device = getTouchDevice();
if (touch_device != nullptr && touch_device->supportsLvgl()) {
touch_device->startLvgl(lvglDisplay);
}
return lvglDisplay != nullptr;
}
bool EspLcdDisplayV2::stopLvgl() {
if (lvglDisplay == nullptr) {
return false;
}
auto touch_device = getTouchDevice();
if (touch_device != nullptr) {
touch_device->stopLvgl();
}
lvgl_port_remove_disp(lvglDisplay);
lvglDisplay = nullptr;
return true;
}
lvgl_port_display_cfg_t EspLcdDisplayV2::getLvglPortDisplayConfig(std::shared_ptr<EspLcdConfiguration> configuration, esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) {
return lvgl_port_display_cfg_t {
.io_handle = ioHandle,
.panel_handle = panelHandle,
.control_handle = nullptr,
.buffer_size = getBufferSize(configuration),
.double_buffer = false,
.trans_size = 0,
.hres = configuration->horizontalResolution,
.vres = configuration->verticalResolution,
.monochrome = configuration->monochrome,
.rotation = {
.swap_xy = configuration->swapXY,
.mirror_x = configuration->mirrorX,
.mirror_y = configuration->mirrorY,
},
.color_format = configuration->lvglColorFormat,
.flags = {
.buff_dma = configuration->buffSpiram ? 0u : 1u,
.buff_spiram = configuration->buffSpiram ? 1u : 0u,
.sw_rotate = configuration->swRotate ? 1u : 0u,
.swap_bytes = configuration->lvglSwapBytes,
.full_refresh = 0,
.direct_mode = 0
}
};
}
std::shared_ptr<tt::hal::display::DisplayDriver> EspLcdDisplayV2::getDisplayDriver() {
assert(lvglDisplay == nullptr); // Still attached to LVGL context. Call stopLvgl() first.
if (displayDriver == nullptr) {
auto lvgl_port_config = getLvglPortDisplayConfig(configuration, ioHandle, panelHandle);
auto panel_config = createPanelConfig(configuration, GPIO_NUM_NC);
tt::hal::display::ColorFormat color_format;
if (lvgl_port_config.color_format == LV_COLOR_FORMAT_I1) {
color_format = tt::hal::display::ColorFormat::Monochrome;
} else if (lvgl_port_config.color_format == LV_COLOR_FORMAT_RGB565) {
if (panel_config.rgb_ele_order == LCD_RGB_ELEMENT_ORDER_RGB) {
if (lvgl_port_config.flags.swap_bytes) {
color_format = tt::hal::display::ColorFormat::RGB565Swapped;
} else {
color_format = tt::hal::display::ColorFormat::RGB565;
}
} else {
if (lvgl_port_config.flags.swap_bytes) {
color_format = tt::hal::display::ColorFormat::BGR565Swapped;
} else {
color_format = tt::hal::display::ColorFormat::BGR565;
}
}
} else if (lvgl_port_config.color_format == LV_COLOR_FORMAT_RGB888) {
color_format = tt::hal::display::ColorFormat::RGB888;
} else {
check(false, "unsupported driver");
}
displayDriver = std::make_shared<EspLcdDisplayDriver>(
panelHandle,
lvgl_port_config.hres,
lvgl_port_config.vres,
color_format
);
}
return displayDriver;
}
@@ -1,114 +0,0 @@
#pragma once
#include <tactility/check.h>
#include <Tactility/hal/display/DisplayDevice.h>
#include <esp_lcd_panel_dev.h>
#include <esp_lcd_types.h>
#include <esp_lvgl_port_disp.h>
constexpr auto DEFAULT_BUFFER_SIZE = 0;
struct EspLcdConfiguration {
unsigned int horizontalResolution;
unsigned int verticalResolution;
int gapX;
int gapY;
bool monochrome;
bool swapXY;
bool mirrorX;
bool mirrorY;
bool invertColor;
uint32_t bufferSize; // Size in pixel count. 0 means default, which is 1/10 of the screen size
bool swRotate = false; // Use LVGL software rotation instead of hardware swap_xy (required for MIPI-DSI panels that don't support swap_xy)
bool buffSpiram = false; // Allocate LVGL draw buffers from PSRAM instead of DMA-capable internal SRAM (required when sw_rotate needs a 3rd buffer that won't fit in internal SRAM)
std::shared_ptr<tt::hal::touch::TouchDevice> touch;
std::function<void(uint8_t)> _Nullable backlightDutyFunction;
gpio_num_t resetPin;
lv_color_format_t lvglColorFormat;
bool lvglSwapBytes;
lcd_rgb_element_order_t rgbElementOrder;
uint32_t bitsPerPixel;
};
class EspLcdDisplayV2 : public tt::hal::display::DisplayDevice {
esp_lcd_panel_io_handle_t _Nullable ioHandle = nullptr;
esp_lcd_panel_handle_t _Nullable panelHandle = nullptr;
lv_display_t* _Nullable lvglDisplay = nullptr;
std::shared_ptr<tt::hal::display::DisplayDriver> _Nullable displayDriver;
std::shared_ptr<EspLcdConfiguration> configuration;
bool applyConfiguration() const;
lvgl_port_display_cfg_t getLvglPortDisplayConfig(std::shared_ptr<EspLcdConfiguration> configuration, esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle);
protected:
virtual bool createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) = 0;
virtual esp_lcd_panel_dev_config_t createPanelConfig(std::shared_ptr<EspLcdConfiguration> espLcdConfiguration, gpio_num_t resetPin) = 0;
virtual bool createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_panel_dev_config_t& panelConfig, esp_lcd_panel_handle_t& panelHandle) = 0;
virtual bool isRgbPanel() const { return false; }
virtual lvgl_port_display_rgb_cfg_t getLvglPortDisplayRgbConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) { check(false, "Not supported"); }
// Hook for MIPI-DSI DPI panels to let LVGL port use DSI-specific path
virtual bool useDsiPanel() const { return false; }
virtual lvgl_port_display_dsi_cfg_t getLvglPortDisplayDsiConfig(esp_lcd_panel_io_handle_t /*ioHandle*/, esp_lcd_panel_handle_t /*panelHandle*/) {
return lvgl_port_display_dsi_cfg_t{ .flags = { .avoid_tearing = 0 } };
}
// Used for sending commands such as setting curves
esp_lcd_panel_io_handle_t getIoHandle() const { return ioHandle; }
public:
explicit EspLcdDisplayV2(const std::shared_ptr<EspLcdConfiguration>& configuration) :
configuration(configuration)
{}
~EspLcdDisplayV2() override;
bool start() final;
bool stop() final;
// region LVGL
bool supportsLvgl() const final { return true; }
bool startLvgl() final;
bool stopLvgl() final;
lv_display_t* _Nullable getLvglDisplay() const final { return lvglDisplay; }
// endregion
std::shared_ptr<tt::hal::touch::TouchDevice> _Nullable getTouchDevice() override { return configuration->touch; }
// region Backlight
void setBacklightDuty(uint8_t backlightDuty) override {
if (configuration->backlightDutyFunction != nullptr) {
configuration->backlightDutyFunction(backlightDuty);
}
}
bool supportsBacklightDuty() const override { return configuration->backlightDutyFunction != nullptr; }
// endregion
// region DisplayDriver
bool supportsDisplayDriver() const override { return true; }
/** @return a NativeDisplay instance if this device supports it */
std::shared_ptr<tt::hal::display::DisplayDriver> _Nullable getDisplayDriver() final;
// endregion
};
@@ -1,70 +0,0 @@
#include "EspLcdSpiDisplay.h"
#include <esp_lcd_panel_commands.h>
#include <tactility/log.h>
constexpr auto* TAG = "EspLcdSpiDisplay";
bool EspLcdSpiDisplay::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
LOG_I(TAG, "createIoHandle");
const esp_lcd_panel_io_spi_config_t panel_io_config = {
.cs_gpio_num = spiConfiguration->csPin,
.dc_gpio_num = spiConfiguration->dcPin,
.spi_mode = 0,
.pclk_hz = spiConfiguration->pixelClockFrequency,
.trans_queue_depth = spiConfiguration->transactionQueueDepth,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0,
.flags = {
.dc_high_on_cmd = 0,
.dc_low_on_data = 0,
.dc_low_on_param = 0,
.octal_mode = 0,
.quad_mode = 0,
.sio_mode = 1,
.lsb_first = 0,
.cs_high_active = 0
}
};
if (esp_lcd_new_panel_io_spi(spiConfiguration->spiHostDevice, &panel_io_config, &outHandle) != ESP_OK) {
LOG_E(TAG, "Failed to create panel");
return false;
}
return true;
}
void EspLcdSpiDisplay::setGammaCurve(uint8_t index) {
uint8_t gamma_curve;
switch (index) {
case 0:
gamma_curve = 0x01;
break;
case 1:
gamma_curve = 0x04;
break;
case 2:
gamma_curve = 0x02;
break;
case 3:
gamma_curve = 0x08;
break;
default:
return;
}
const uint8_t param[] = {
gamma_curve
};
auto io_handle = getIoHandle();
assert(io_handle != nullptr);
if (esp_lcd_panel_io_tx_param(io_handle, LCD_CMD_GAMSET, param, 1) != ESP_OK) {
LOG_E(TAG, "Failed to set gamma");
}
}
@@ -1,49 +0,0 @@
#pragma once
#include "EspLcdDisplayV2.h"
#include <driver/spi_common.h>
#include <esp_lcd_io_spi.h>
#include <esp_lcd_types.h>
/**
* Adds IO implementations on top of EspLcdDisplayV2
* @warning This is an abstract class. You need to extend it to use it.
*/
class EspLcdSpiDisplay : public EspLcdDisplayV2 {
public:
struct SpiConfiguration {
spi_host_device_t spiHostDevice;
gpio_num_t csPin;
gpio_num_t dcPin;
unsigned int pixelClockFrequency = 80'000'000; // Hertz
size_t transactionQueueDepth = 10;
};
explicit EspLcdSpiDisplay(const std::shared_ptr<EspLcdConfiguration>& configuration, const std::shared_ptr<SpiConfiguration> spiConfiguration, int gammaCurveCount) :
EspLcdDisplayV2(configuration),
spiConfiguration(spiConfiguration),
gammaCurveCount(gammaCurveCount)
{}
private:
std::shared_ptr<SpiConfiguration> spiConfiguration;
int gammaCurveCount;
protected:
bool createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) override;
// region Gamma
void setGammaCurve(uint8_t index) override;
uint8_t getGammaCurveCount() const override { return gammaCurveCount; }
// endregion
};
@@ -1,93 +0,0 @@
#include "EspLcdTouch.h"
#include <EspLcdTouchDriver.h>
#include <tactility/log.h>
#include <esp_lvgl_port_touch.h>
constexpr auto* TAG = "EspLcdTouch";
bool EspLcdTouch::start() {
if (!createIoHandle(ioHandle) != ESP_OK) {
LOG_E(TAG, "Touch IO failed");
return false;
}
config = createEspLcdTouchConfig();
if (!createTouchHandle(ioHandle, config, touchHandle)) {
LOG_E(TAG, "Driver init failed");
esp_lcd_panel_io_del(ioHandle);
ioHandle = nullptr;
return false;
}
return true;
}
bool EspLcdTouch::stop() {
if (lvglDevice != nullptr) {
stopLvgl();
}
if (ioHandle != nullptr) {
esp_lcd_panel_io_del(ioHandle);
ioHandle = nullptr;
}
if (touchHandle != nullptr) {
esp_lcd_touch_del(touchHandle);
touchHandle = nullptr;
}
return true;
}
bool EspLcdTouch::startLvgl(lv_disp_t* display) {
if (lvglDevice != nullptr) {
return false;
}
if (touchDriver != nullptr && touchDriver.use_count() > 1) {
LOG_W(TAG, "TouchDriver is still in use.");
}
const lvgl_port_touch_cfg_t touch_cfg = {
.disp = display,
.handle = touchHandle,
};
LOG_I(TAG, "Adding touch to LVGL");
lvglDevice = lvgl_port_add_touch(&touch_cfg);
if (lvglDevice == nullptr) {
LOG_E(TAG, "Adding touch failed");
return false;
}
return true;
}
bool EspLcdTouch::stopLvgl() {
if (lvglDevice == nullptr) {
return false;
}
lvgl_port_remove_touch(lvglDevice);
lvglDevice = nullptr;
return true;
}
std::shared_ptr<tt::hal::touch::TouchDriver> _Nullable EspLcdTouch::getTouchDriver() {
assert(lvglDevice == nullptr); // Still attached to LVGL context. Call stopLvgl() first.
if (touchHandle == nullptr) {
return nullptr;
}
if (touchDriver == nullptr) {
touchDriver = std::make_shared<EspLcdTouchDriver>(touchHandle);
}
return touchDriver;
}
-44
View File
@@ -1,44 +0,0 @@
#pragma once
#include <esp_lcd_touch.h>
#include <esp_lcd_types.h>
#include <lvgl.h>
#include <Tactility/hal/touch/TouchDevice.h>
#include <Tactility/hal/touch/TouchDriver.h>
class EspLcdTouch : public tt::hal::touch::TouchDevice {
esp_lcd_touch_config_t config;
esp_lcd_panel_io_handle_t _Nullable ioHandle = nullptr;
esp_lcd_touch_handle_t _Nullable touchHandle = nullptr;
lv_indev_t* lvglDevice = nullptr;
std::shared_ptr<tt::hal::touch::TouchDriver> touchDriver;
protected:
esp_lcd_touch_handle_t _Nullable getTouchHandle() const { return touchHandle; }
virtual bool createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) = 0;
virtual bool createTouchHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_touch_config_t& configuration, esp_lcd_touch_handle_t& touchHandle) = 0;
virtual esp_lcd_touch_config_t createEspLcdTouchConfig() = 0;
public:
bool start() final;
bool stop() final;
bool supportsLvgl() const final { return true; }
bool startLvgl(lv_display_t* display) final;
bool stopLvgl() final;
lv_indev_t* getLvglIndev() final { return lvglDevice; }
bool supportsTouchDriver() override { return true; }
std::shared_ptr<tt::hal::touch::TouchDriver> _Nullable getTouchDriver() final;
};
@@ -1,13 +0,0 @@
#include "EspLcdTouchDriver.h"
#include <tactility/log.h>
constexpr auto* TAG = "EspLcdTouchDriver";
bool EspLcdTouchDriver::getTouchedPoints(uint16_t* x, uint16_t* y, uint16_t* _Nullable strength, uint8_t* pointCount, uint8_t maxPointCount) {
if (esp_lcd_touch_read_data(handle) != ESP_OK) {
LOG_E(TAG, "Read data failed");
return false;
}
return esp_lcd_touch_get_coordinates(handle, x, y, strength, pointCount, maxPointCount);
}
@@ -1,15 +0,0 @@
#pragma once
#include <esp_lcd_touch.h>
#include <Tactility/hal/touch/TouchDriver.h>
class EspLcdTouchDriver final : public tt::hal::touch::TouchDriver {
esp_lcd_touch_handle_t handle;
public:
EspLcdTouchDriver(esp_lcd_touch_handle_t handle) : handle(handle) {}
bool getTouchedPoints(uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* pointCount, uint8_t maxPointCount) override;
};
-5
View File
@@ -1,5 +0,0 @@
idf_component_register(
SRC_DIRS "Source"
INCLUDE_DIRS "Source"
REQUIRES Tactility driver
)

Some files were not shown because too many files have changed in this diff Show More