First test
This commit is contained in:
commit
3eb49b31af
13
.devcontainer/Dockerfile
Normal file
13
.devcontainer/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
ARG DOCKER_TAG=latest
|
||||||
|
FROM espressif/idf:${DOCKER_TAG}
|
||||||
|
|
||||||
|
ENV LC_ALL=C.UTF-8
|
||||||
|
ENV LANG=C.UTF-8
|
||||||
|
|
||||||
|
RUN apt-get update -y && apt-get install udev -y
|
||||||
|
|
||||||
|
RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/opt/esp/entrypoint.sh" ]
|
||||||
|
|
||||||
|
CMD ["/bin/bash", "-c"]
|
||||||
19
.devcontainer/devcontainer.json
Normal file
19
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "ESP-IDF QEMU",
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile"
|
||||||
|
},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"settings": {
|
||||||
|
"terminal.integrated.defaultProfile.linux": "bash",
|
||||||
|
"idf.gitPath": "/usr/bin/git"
|
||||||
|
},
|
||||||
|
"extensions": [
|
||||||
|
"espressif.esp-idf-extension",
|
||||||
|
"espressif.esp-idf-web"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"runArgs": ["--privileged"]
|
||||||
|
}
|
||||||
78
.gitignore
vendored
Normal file
78
.gitignore
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Directory metadata
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*~
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Build artifacts and directories
|
||||||
|
**/build/
|
||||||
|
build/
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.out
|
||||||
|
*.exe # For any host-side utilities compiled on Windows
|
||||||
|
|
||||||
|
# ESP-IDF specific build outputs
|
||||||
|
*.bin
|
||||||
|
*.elf
|
||||||
|
*.map
|
||||||
|
flasher_args.json # Generated in build directory
|
||||||
|
sdkconfig.old
|
||||||
|
sdkconfig
|
||||||
|
|
||||||
|
# ESP-IDF dependencies
|
||||||
|
# For older versions or manual component management
|
||||||
|
/components/.idf/
|
||||||
|
**/components/.idf/
|
||||||
|
# For modern ESP-IDF component manager
|
||||||
|
managed_components/
|
||||||
|
# If ESP-IDF tools are installed/referenced locally to the project
|
||||||
|
.espressif/
|
||||||
|
|
||||||
|
# CMake generated files
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
CTestTestfile.cmake
|
||||||
|
|
||||||
|
# Python environment files
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
__pycache__/
|
||||||
|
*.egg-info/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# Virtual environment folders
|
||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
env/
|
||||||
|
|
||||||
|
# Language Servers
|
||||||
|
.clangd/
|
||||||
|
.ccls-cache/
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
# Windows specific
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# User-specific configuration files
|
||||||
|
*.user
|
||||||
|
*.workspace # General workspace files, can be from various tools
|
||||||
|
*.suo # Visual Studio Solution User Options
|
||||||
|
*.sln.docstates # Visual Studio
|
||||||
19
.vscode/c_cpp_properties.json
vendored
Normal file
19
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "ESP-IDF",
|
||||||
|
"compilerPath": "/home/thomas/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20251107/riscv32-esp-elf/bin/riscv32-esp-elf-gcc",
|
||||||
|
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"browse": {
|
||||||
|
"path": [
|
||||||
|
"${workspaceFolder}"
|
||||||
|
],
|
||||||
|
"limitSymbolsToIncludedHeaders": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "gdbtarget",
|
||||||
|
"request": "attach",
|
||||||
|
"name": "Eclipse CDT GDB Adapter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "espidf",
|
||||||
|
"name": "Launch",
|
||||||
|
"request": "launch"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
18
.vscode/settings.json
vendored
Normal file
18
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"C_Cpp.intelliSenseEngine": "default",
|
||||||
|
"idf.openOcdConfigs": [
|
||||||
|
"interface/ftdi/esp32_devkitj_v1.cfg",
|
||||||
|
"target/esp32.cfg"
|
||||||
|
],
|
||||||
|
"idf.port": "/dev/ttyACM0",
|
||||||
|
"idf.currentSetup": "/home/thomas/.espressif/v5.5.2/esp-idf",
|
||||||
|
"idf.customExtraVars": {
|
||||||
|
"IDF_TARGET": "esp32p4"
|
||||||
|
},
|
||||||
|
"clangd.path": "/home/thomas/.espressif/tools/esp-clang/esp-19.1.2_20250312/esp-clang/bin/clangd",
|
||||||
|
"clangd.arguments": [
|
||||||
|
"--background-index",
|
||||||
|
"--query-driver=/home/thomas/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20251107/riscv32-esp-elf/bin/riscv32-esp-elf-gcc",
|
||||||
|
"--compile-commands-dir=/home/thomas/projekte/test1/display/build"
|
||||||
|
]
|
||||||
|
}
|
||||||
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||||
|
# idf_build_set_property(MINIMAL_BUILD ON)
|
||||||
|
project(knxdisplay)
|
||||||
53
README.md
Normal file
53
README.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | Linux |
|
||||||
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | ----- |
|
||||||
|
|
||||||
|
# Hello World Example
|
||||||
|
|
||||||
|
Starts a FreeRTOS task to print "Hello World".
|
||||||
|
|
||||||
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
|
## How to use example
|
||||||
|
|
||||||
|
Follow detailed instructions provided specifically for this example.
|
||||||
|
|
||||||
|
Select the instructions depending on Espressif chip installed on your development board:
|
||||||
|
|
||||||
|
- [ESP32 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html)
|
||||||
|
- [ESP32-S2 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html)
|
||||||
|
|
||||||
|
|
||||||
|
## Example folder contents
|
||||||
|
|
||||||
|
The project **hello_world** contains one source file in C language [hello_world_main.c](main/hello_world_main.c). The file is located in folder [main](main).
|
||||||
|
|
||||||
|
ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt` files that provide set of directives and instructions describing the project's source files and targets (executable, library, or both).
|
||||||
|
|
||||||
|
Below is short explanation of remaining files in the project folder.
|
||||||
|
|
||||||
|
```
|
||||||
|
├── CMakeLists.txt
|
||||||
|
├── pytest_hello_world.py Python script used for automated testing
|
||||||
|
├── main
|
||||||
|
│ ├── CMakeLists.txt
|
||||||
|
│ └── hello_world_main.c
|
||||||
|
└── README.md This is the file you are currently reading
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information on structure and contents of ESP-IDF projects, please refer to Section [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html) of the ESP-IDF Programming Guide.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
* Program upload failure
|
||||||
|
|
||||||
|
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
|
||||||
|
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
|
||||||
|
|
||||||
|
## Technical support and feedback
|
||||||
|
|
||||||
|
Please use the following feedback channels:
|
||||||
|
|
||||||
|
* For technical queries, go to the [esp32.com](https://esp32.com/) forum
|
||||||
|
* For a feature request or bug report, create a [GitHub issue](https://github.com/espressif/esp-idf/issues)
|
||||||
|
|
||||||
|
We will get back to you as soon as possible.
|
||||||
110
dependencies.lock
Normal file
110
dependencies.lock
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
dependencies:
|
||||||
|
espressif/cmake_utilities:
|
||||||
|
component_hash:
|
||||||
|
351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
|
||||||
|
dependencies:
|
||||||
|
- name: idf
|
||||||
|
require: private
|
||||||
|
version: '>=4.1'
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com
|
||||||
|
type: service
|
||||||
|
version: 0.5.3
|
||||||
|
espressif/esp_lcd_touch:
|
||||||
|
component_hash:
|
||||||
|
3f85a7d95af876f1a6ecca8eb90a81614890d0f03a038390804e5a77e2caf862
|
||||||
|
dependencies:
|
||||||
|
- name: idf
|
||||||
|
require: private
|
||||||
|
version: '>=4.4.2'
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com
|
||||||
|
type: service
|
||||||
|
version: 1.2.1
|
||||||
|
espressif/esp_lcd_touch_gt911:
|
||||||
|
component_hash:
|
||||||
|
be02e243d18b9a661bc13b0d22c0a5cfa3f708cf04d6eb059772276c8c8a4d76
|
||||||
|
dependencies:
|
||||||
|
- name: espressif/esp_lcd_touch
|
||||||
|
registry_url: https://components.espressif.com
|
||||||
|
require: public
|
||||||
|
version: ^1.2.0
|
||||||
|
- name: idf
|
||||||
|
require: private
|
||||||
|
version: '>=4.4.2'
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 1.2.0~1
|
||||||
|
espressif/esp_lvgl_port:
|
||||||
|
component_hash:
|
||||||
|
f872401524cb645ee6ff1c9242d44fb4ddcfd4d37d7be8b9ed3f4e85a404efcd
|
||||||
|
dependencies:
|
||||||
|
- name: idf
|
||||||
|
require: private
|
||||||
|
version: '>=5.1'
|
||||||
|
- name: lvgl/lvgl
|
||||||
|
registry_url: https://components.espressif.com
|
||||||
|
require: public
|
||||||
|
version: '>=8,<10'
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 2.7.0
|
||||||
|
espressif/i2c_bus:
|
||||||
|
component_hash:
|
||||||
|
4e990dc11734316186b489b362c61d41f23f79d58bc169795cec215e528cba14
|
||||||
|
dependencies:
|
||||||
|
- name: espressif/cmake_utilities
|
||||||
|
registry_url: https://components.espressif.com
|
||||||
|
require: private
|
||||||
|
version: '*'
|
||||||
|
- name: idf
|
||||||
|
require: private
|
||||||
|
version: '>=4.0'
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com
|
||||||
|
type: service
|
||||||
|
version: 1.5.0
|
||||||
|
idf:
|
||||||
|
source:
|
||||||
|
type: idf
|
||||||
|
version: 5.5.2
|
||||||
|
lvgl/lvgl:
|
||||||
|
component_hash:
|
||||||
|
17e68bfd21f0edf4c3ee838e2273da840bf3930e5dbc3bfa6c1190c3aed41f9f
|
||||||
|
dependencies: []
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 9.4.0
|
||||||
|
waveshare/esp_lcd_jd9365_10_1:
|
||||||
|
component_hash:
|
||||||
|
6c1336b93a37df2b5be42c49c4c364d0bacdbf96f053a934f881349457fac679
|
||||||
|
dependencies:
|
||||||
|
- name: espressif/cmake_utilities
|
||||||
|
registry_url: https://components.espressif.com
|
||||||
|
require: private
|
||||||
|
version: 0.*
|
||||||
|
- name: espressif/i2c_bus
|
||||||
|
registry_url: https://components.espressif.com
|
||||||
|
require: private
|
||||||
|
version: ^1.3.0
|
||||||
|
- name: idf
|
||||||
|
require: private
|
||||||
|
version: '>=5.3'
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com/
|
||||||
|
type: service
|
||||||
|
targets:
|
||||||
|
- esp32p4
|
||||||
|
version: 1.0.4
|
||||||
|
direct_dependencies:
|
||||||
|
- espressif/esp_lcd_touch_gt911
|
||||||
|
- espressif/esp_lvgl_port
|
||||||
|
- idf
|
||||||
|
- lvgl/lvgl
|
||||||
|
- waveshare/esp_lcd_jd9365_10_1
|
||||||
|
manifest_hash: 1b3972520800645b8020e1ad5d7fcfe89a9006c17fff1fcaa83ae8df9e2314ff
|
||||||
|
target: esp32p4
|
||||||
|
version: 2.0.0
|
||||||
4
main/CMakeLists.txt
Normal file
4
main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
idf_component_register(SRCS "hello_world_main.c"
|
||||||
|
PRIV_REQUIRES spi_flash esp_lcd
|
||||||
|
REQUIRES esp_timer lvgl
|
||||||
|
INCLUDE_DIRS "")
|
||||||
265
main/hello_world_main.c
Normal file
265
main/hello_world_main.c
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 User
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "driver/i2c_master.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "esp_lcd_panel_ops.h"
|
||||||
|
#include "esp_lcd_panel_io.h"
|
||||||
|
#include "esp_lcd_mipi_dsi.h"
|
||||||
|
#include "esp_ldo_regulator.h"
|
||||||
|
#include "esp_lcd_touch_gt911.h"
|
||||||
|
#include "lvgl.h"
|
||||||
|
#include "esp_lcd_jd9365_10_1.h"
|
||||||
|
|
||||||
|
#define TAG "JD9365_LVGL"
|
||||||
|
|
||||||
|
// Display config
|
||||||
|
#define LCD_H_RES 800
|
||||||
|
#define LCD_V_RES 1280
|
||||||
|
#define LCD_BIT_PER_PIXEL 24
|
||||||
|
#define LCD_RST_GPIO 27
|
||||||
|
#define LCD_BK_GPIO 26
|
||||||
|
#define LCD_BK_ON_LEVEL 1
|
||||||
|
|
||||||
|
// MIPI DSI config
|
||||||
|
#define MIPI_DSI_LANE_NUM 2
|
||||||
|
#define MIPI_DSI_PHY_LDO_CHAN 3
|
||||||
|
#define MIPI_DSI_PHY_LDO_VOLTAGE_MV 2500
|
||||||
|
|
||||||
|
// Touch config (GT911)
|
||||||
|
#define TOUCH_I2C_SDA 7
|
||||||
|
#define TOUCH_I2C_SCL 8
|
||||||
|
#define TOUCH_INT_GPIO 3
|
||||||
|
#define TOUCH_RST_GPIO 2
|
||||||
|
#define TOUCH_I2C_FREQ_HZ 400000
|
||||||
|
|
||||||
|
static esp_lcd_panel_handle_t panel_handle = NULL;
|
||||||
|
static esp_lcd_touch_handle_t touch_handle = NULL;
|
||||||
|
static esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
|
||||||
|
static esp_lcd_panel_io_handle_t mipi_dbi_io = NULL;
|
||||||
|
static SemaphoreHandle_t refresh_done_sem = NULL;
|
||||||
|
|
||||||
|
// ================= Color Transfer Done Callback ===================
|
||||||
|
static bool on_color_trans_done(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *event_data, void *user_ctx)
|
||||||
|
{
|
||||||
|
BaseType_t high_task_awoken = pdFALSE;
|
||||||
|
if (refresh_done_sem) {
|
||||||
|
xSemaphoreGiveFromISR(refresh_done_sem, &high_task_awoken);
|
||||||
|
}
|
||||||
|
return high_task_awoken == pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ================= Flush Callback ===================
|
||||||
|
static void lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *color_p)
|
||||||
|
{
|
||||||
|
xSemaphoreTake(refresh_done_sem, portMAX_DELAY);
|
||||||
|
|
||||||
|
esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1,
|
||||||
|
area->x2 + 1, area->y2 + 1, color_p);
|
||||||
|
|
||||||
|
lv_display_flush_ready(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= MIPI DSI / JD9365 init ===================
|
||||||
|
static void lcd_init(void)
|
||||||
|
{
|
||||||
|
// Backlight GPIO
|
||||||
|
gpio_config_t bk_gpio = {
|
||||||
|
.mode = GPIO_MODE_OUTPUT,
|
||||||
|
.pin_bit_mask = 1ULL << LCD_BK_GPIO
|
||||||
|
};
|
||||||
|
gpio_config(&bk_gpio);
|
||||||
|
gpio_set_level(LCD_BK_GPIO, LCD_BK_ON_LEVEL);
|
||||||
|
|
||||||
|
// LDO für MIPI PHY
|
||||||
|
esp_ldo_channel_handle_t ldo_mipi = NULL;
|
||||||
|
esp_ldo_channel_config_t ldo_cfg = {
|
||||||
|
.chan_id = MIPI_DSI_PHY_LDO_CHAN,
|
||||||
|
.voltage_mv = MIPI_DSI_PHY_LDO_VOLTAGE_MV
|
||||||
|
};
|
||||||
|
esp_ldo_acquire_channel(&ldo_cfg, &ldo_mipi);
|
||||||
|
|
||||||
|
// MIPI DSI Bus
|
||||||
|
esp_lcd_dsi_bus_config_t bus_cfg = JD9365_PANEL_BUS_DSI_2CH_CONFIG();
|
||||||
|
esp_lcd_new_dsi_bus(&bus_cfg, &mipi_dsi_bus);
|
||||||
|
|
||||||
|
// Panel IO
|
||||||
|
esp_lcd_dbi_io_config_t io_cfg = JD9365_PANEL_IO_DBI_CONFIG();
|
||||||
|
esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &io_cfg, &mipi_dbi_io);
|
||||||
|
|
||||||
|
// Panel Driver
|
||||||
|
esp_lcd_dpi_panel_config_t dpi_cfg = JD9365_800_1280_PANEL_60HZ_DPI_CONFIG(LCD_COLOR_PIXEL_FORMAT_RGB888);
|
||||||
|
jd9365_vendor_config_t vendor_cfg = {
|
||||||
|
.flags = { .use_mipi_interface = 1 },
|
||||||
|
.mipi_config = { .dsi_bus = mipi_dsi_bus, .dpi_config = &dpi_cfg, .lane_num = MIPI_DSI_LANE_NUM }
|
||||||
|
};
|
||||||
|
esp_lcd_panel_dev_config_t panel_cfg = {
|
||||||
|
.reset_gpio_num = LCD_RST_GPIO,
|
||||||
|
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||||
|
.bits_per_pixel = LCD_BIT_PER_PIXEL,
|
||||||
|
.vendor_config = &vendor_cfg
|
||||||
|
};
|
||||||
|
esp_lcd_new_panel_jd9365(mipi_dbi_io, &panel_cfg, &panel_handle);
|
||||||
|
|
||||||
|
// Initialize panel first
|
||||||
|
esp_lcd_panel_reset(panel_handle);
|
||||||
|
esp_lcd_panel_init(panel_handle);
|
||||||
|
esp_lcd_panel_disp_on_off(panel_handle, true);
|
||||||
|
|
||||||
|
// Now set up synchronization after panel is ready
|
||||||
|
refresh_done_sem = xSemaphoreCreateBinary();
|
||||||
|
xSemaphoreGive(refresh_done_sem); // Allow first draw to proceed
|
||||||
|
|
||||||
|
// Register color transfer done callback (signals when draw_bitmap completes)
|
||||||
|
esp_lcd_dpi_panel_event_callbacks_t cbs = {
|
||||||
|
.on_color_trans_done = on_color_trans_done,
|
||||||
|
};
|
||||||
|
esp_lcd_dpi_panel_register_event_callbacks(panel_handle, &cbs, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= Touch init ===================
|
||||||
|
static void touch_init(void)
|
||||||
|
{
|
||||||
|
// I2C Bus initialisieren
|
||||||
|
i2c_master_bus_config_t i2c_bus_cfg = {
|
||||||
|
.i2c_port = I2C_NUM_0,
|
||||||
|
.sda_io_num = TOUCH_I2C_SDA,
|
||||||
|
.scl_io_num = TOUCH_I2C_SCL,
|
||||||
|
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||||
|
.glitch_ignore_cnt = 7,
|
||||||
|
.flags.enable_internal_pullup = true, // Board hat externe Pullups
|
||||||
|
};
|
||||||
|
i2c_master_bus_handle_t i2c_bus = NULL;
|
||||||
|
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus));
|
||||||
|
|
||||||
|
// Touch Panel IO
|
||||||
|
esp_lcd_panel_io_handle_t touch_io = NULL;
|
||||||
|
esp_lcd_panel_io_i2c_config_t touch_io_cfg = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG();
|
||||||
|
touch_io_cfg.scl_speed_hz = TOUCH_I2C_FREQ_HZ;
|
||||||
|
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus, &touch_io_cfg, &touch_io));
|
||||||
|
|
||||||
|
// GT911 Touch Controller
|
||||||
|
esp_lcd_touch_config_t touch_cfg = {
|
||||||
|
.x_max = LCD_H_RES,
|
||||||
|
.y_max = LCD_V_RES,
|
||||||
|
.rst_gpio_num = TOUCH_RST_GPIO,
|
||||||
|
.int_gpio_num = TOUCH_INT_GPIO,
|
||||||
|
.levels = {
|
||||||
|
.reset = 0,
|
||||||
|
.interrupt = 0,
|
||||||
|
},
|
||||||
|
.flags = {
|
||||||
|
.swap_xy = 0,
|
||||||
|
.mirror_x = 0,
|
||||||
|
.mirror_y = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(touch_io, &touch_cfg, &touch_handle));
|
||||||
|
ESP_LOGI(TAG, "Touch GT911 initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= LVGL Touch Callback ===================
|
||||||
|
static void lvgl_touch_cb(lv_indev_t *indev, lv_indev_data_t *data)
|
||||||
|
{
|
||||||
|
uint16_t x[1];
|
||||||
|
uint16_t y[1];
|
||||||
|
uint8_t touch_cnt = 0;
|
||||||
|
|
||||||
|
esp_lcd_touch_read_data(touch_handle);
|
||||||
|
bool touched = esp_lcd_touch_get_coordinates(touch_handle, x, y, NULL, &touch_cnt, 1);
|
||||||
|
|
||||||
|
if (touched && touch_cnt > 0) {
|
||||||
|
data->point.x = x[0];
|
||||||
|
data->point.y = y[0];
|
||||||
|
data->state = LV_INDEV_STATE_PRESSED;
|
||||||
|
} else {
|
||||||
|
data->state = LV_INDEV_STATE_RELEASED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= LVGL init ===================
|
||||||
|
static void lvgl_init(void)
|
||||||
|
{
|
||||||
|
lv_init();
|
||||||
|
|
||||||
|
// Display erstellen
|
||||||
|
lv_display_t* display1 = lv_display_create(LCD_H_RES, LCD_V_RES);
|
||||||
|
|
||||||
|
// Set color format to match panel (RGB888 = 24-bit)
|
||||||
|
lv_display_set_color_format(display1, LV_COLOR_FORMAT_RGB888);
|
||||||
|
|
||||||
|
// Allocate buffers in PSRAM with proper alignment for DMA
|
||||||
|
size_t buf_size = LCD_H_RES * 100 * 3; // 100 lines at a time, RGB888
|
||||||
|
uint8_t *buf1 = heap_caps_aligned_alloc(64, buf_size,
|
||||||
|
MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
|
||||||
|
uint8_t *buf2 = heap_caps_aligned_alloc(64, buf_size,
|
||||||
|
MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
|
||||||
|
|
||||||
|
if (!buf1 || !buf2) {
|
||||||
|
ESP_LOGE(TAG, "Failed to allocate display buffers!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_display_set_buffers(display1, buf1, buf2, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||||
|
|
||||||
|
// Flush-Callback setzen
|
||||||
|
lv_display_set_flush_cb(display1, lvgl_flush_cb);
|
||||||
|
|
||||||
|
// Touch Input Device registrieren
|
||||||
|
lv_indev_t *indev = lv_indev_create();
|
||||||
|
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
|
||||||
|
lv_indev_set_read_cb(indev, lvgl_touch_cb);
|
||||||
|
lv_indev_set_display(indev, display1);
|
||||||
|
|
||||||
|
lv_display_set_default(display1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= Button Callback ===================
|
||||||
|
static void btn_event_cb(lv_event_t *e)
|
||||||
|
{
|
||||||
|
lv_event_code_t code = lv_event_get_code(e);
|
||||||
|
if (code == LV_EVENT_CLICKED) {
|
||||||
|
ESP_LOGI(TAG, "Button clicked!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= UI erstellen ===================
|
||||||
|
static void create_ui(void)
|
||||||
|
{
|
||||||
|
// Button erstellen
|
||||||
|
lv_obj_t *btn = lv_button_create(lv_screen_active());
|
||||||
|
lv_obj_set_size(btn, 200, 80);
|
||||||
|
lv_obj_center(btn);
|
||||||
|
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);
|
||||||
|
|
||||||
|
// Label auf dem Button
|
||||||
|
lv_obj_t *label = lv_label_create(btn);
|
||||||
|
lv_label_set_text(label, "Klick mich!");
|
||||||
|
lv_obj_center(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= Main ===================
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Starting JD9365 + LVGL 9");
|
||||||
|
|
||||||
|
lcd_init();
|
||||||
|
touch_init();
|
||||||
|
lvgl_init();
|
||||||
|
create_ui();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
lv_tick_inc(10);
|
||||||
|
lv_task_handler();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
20
main/idf_component.yml
Normal file
20
main/idf_component.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
## IDF Component Manager Manifest File
|
||||||
|
dependencies:
|
||||||
|
## Required IDF version
|
||||||
|
idf:
|
||||||
|
version: '>=4.1.0'
|
||||||
|
# # Put list of dependencies here
|
||||||
|
# # For components maintained by Espressif:
|
||||||
|
# component: "~1.0.0"
|
||||||
|
# # For 3rd party components:
|
||||||
|
# username/component: ">=1.0.0,<2.0.0"
|
||||||
|
# username2/component2:
|
||||||
|
# version: "~1.0.0"
|
||||||
|
# # For transient dependencies `public` flag can be set.
|
||||||
|
# # `public` flag doesn't have an effect dependencies of the `main` component.
|
||||||
|
# # All dependencies of `main` are public by default.
|
||||||
|
# public: true
|
||||||
|
waveshare/esp_lcd_jd9365_10_1: '*'
|
||||||
|
lvgl/lvgl: ^9.4.0
|
||||||
|
espressif/esp_lvgl_port: ^2.3.0
|
||||||
|
espressif/esp_lcd_touch_gt911: '*'
|
||||||
55
pytest_hello_world.py
Normal file
55
pytest_hello_world.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
import hashlib
|
||||||
|
import logging
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded_idf.dut import IdfDut
|
||||||
|
from pytest_embedded_idf.utils import idf_parametrize
|
||||||
|
from pytest_embedded_qemu.app import QemuApp
|
||||||
|
from pytest_embedded_qemu.dut import QemuDut
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.generic
|
||||||
|
@idf_parametrize('target', ['supported_targets', 'preview_targets'], indirect=['target'])
|
||||||
|
def test_hello_world(dut: IdfDut, log_minimum_free_heap_size: Callable[..., None]) -> None:
|
||||||
|
dut.expect('Hello world!')
|
||||||
|
log_minimum_free_heap_size()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.host_test
|
||||||
|
@idf_parametrize('target', ['linux'], indirect=['target'])
|
||||||
|
def test_hello_world_linux(dut: IdfDut) -> None:
|
||||||
|
dut.expect('Hello world!')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.host_test
|
||||||
|
@pytest.mark.macos_shell
|
||||||
|
@idf_parametrize('target', ['linux'], indirect=['target'])
|
||||||
|
def test_hello_world_macos(dut: IdfDut) -> None:
|
||||||
|
dut.expect('Hello world!')
|
||||||
|
|
||||||
|
|
||||||
|
def verify_elf_sha256_embedding(app: QemuApp, sha256_reported: str) -> None:
|
||||||
|
sha256 = hashlib.sha256()
|
||||||
|
with open(app.elf_file, 'rb') as f:
|
||||||
|
sha256.update(f.read())
|
||||||
|
sha256_expected = sha256.hexdigest()
|
||||||
|
|
||||||
|
logging.info(f'ELF file SHA256: {sha256_expected}')
|
||||||
|
logging.info(f'ELF file SHA256 (reported by the app): {sha256_reported}')
|
||||||
|
|
||||||
|
# the app reports only the first several hex characters of the SHA256, check that they match
|
||||||
|
if not sha256_expected.startswith(sha256_reported):
|
||||||
|
raise ValueError('ELF file SHA256 mismatch')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.host_test
|
||||||
|
@pytest.mark.qemu
|
||||||
|
@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target'])
|
||||||
|
def test_hello_world_host(app: QemuApp, dut: QemuDut) -> None:
|
||||||
|
sha256_reported = dut.expect(r'ELF file SHA256:\s+([a-f0-9]+)').group(1).decode('utf-8')
|
||||||
|
verify_elf_sha256_embedding(app, sha256_reported)
|
||||||
|
|
||||||
|
dut.expect('Hello world!')
|
||||||
0
sdkconfig.ci
Normal file
0
sdkconfig.ci
Normal file
Loading…
Reference in New Issue
Block a user