commit abeb79151108a25653068b5c6f2b9cc324e9e983 Author: Peter Siegmund Date: Fri Apr 19 16:42:57 2024 +0200 initial commit it compiles, but didn't show anything on the screen yet Signed-off-by: Peter Siegmund diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..1fe78dc --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,47 @@ +FROM espressif/idf + +ARG DEBIAN_FRONTEND=nointeractive +ARG CONTAINER_USER=esp +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +RUN apt-get update \ + && apt install -y -q \ + cmake \ + git \ + libglib2.0-0 \ + libnuma1 \ + libpixman-1-0 \ + && rm -rf /var/lib/apt/lists/* + +# QEMU +ENV QEMU_REL=esp_develop_8.2.0_20240122 +ENV QEMU_SHA256=e7c72ef5705ad1444d391711088c8717fc89f42e9bf6d1487f9c2a326b8cfa83 +ENV QEMU_DIST=qemu-xtensa-softmmu-${QEMU_REL}-x86_64-linux-gnu.tar.xz +ENV QEMU_URL=https://github.com/espressif/qemu/releases/download/esp-develop-8.2.0-20240122/${QEMU_DIST} + +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 + +RUN wget --no-verbose ${QEMU_URL} \ + && echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - \ + && tar -xf $QEMU_DIST -C /opt \ + && rm ${QEMU_DIST} + +ENV PATH=/opt/qemu/bin:${PATH} + +RUN groupadd --gid $USER_GID $CONTAINER_USER \ + && adduser --uid $USER_UID --gid $USER_GID --disabled-password --gecos "" ${CONTAINER_USER} \ + && usermod -a -G root $CONTAINER_USER && usermod -a -G dialout $CONTAINER_USER + +RUN chmod -R 775 /opt/esp/python_env/ + +USER ${CONTAINER_USER} +ENV USER=${CONTAINER_USER} +WORKDIR /home/${CONTAINER_USER} + +RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc + +ENTRYPOINT [ "/opt/esp/entrypoint.sh" ] + +CMD ["/bin/bash", "-c"] \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..1d913ec --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,45 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.183.0/containers/ubuntu +{ + "name": "ESP-IDF QEMU", + "build": { + "dockerfile": "Dockerfile" + }, + // Add the IDs of extensions you want installed when the container is created + "workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind", + /* the path of workspace folder to be opened after container is running + */ + "workspaceFolder": "${localWorkspaceFolder}", + "mounts": [ + "source=extensionCache,target=/root/.vscode-server/extensions,type=volume" + ], + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.defaultProfile.linux": "bash", + "idf.espIdfPath": "/opt/esp/idf", + "idf.customExtraPaths": "", + "idf.pythonBinPath": "/opt/esp/python_env/idf5.3_py3.10_env/bin/python", + "idf.toolsPath": "/opt/esp", + "idf.gitPath": "/usr/bin/git" + }, + "extensions": [ + "espressif.esp-idf-extension" + ], + }, + "codespaces": { + "settings": { + "terminal.integrated.defaultProfile.linux": "bash", + "idf.espIdfPath": "/opt/esp/idf", + "idf.customExtraPaths": "", + "idf.pythonBinPath": "/opt/esp/python_env/idf5.3_py3.10_env/bin/python", + "idf.toolsPath": "/opt/esp", + "idf.gitPath": "/usr/bin/git" + }, + "extensions": [ + "espressif.esp-idf-extension" + ], + } + }, + "runArgs": ["--privileged"] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..498ff5f --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# esp-idf +build/ +sdkconfig +sdkconfig.old + +### VisualStudioCode ### +.vscode/* +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e4f4eea --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "components/lvgl"] + path = components/lvgl + url = git@github.com:lvgl/lvgl.git diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..6d2236f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,10 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "espidf", + "name": "Launch", + "request": "launch" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..1dc7915 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,259 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build - Build project", + "type": "shell", + "command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py build", + "windows": { + "command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py build", + "options": { + "env": { + "PATH": "${env:PATH};${config:idf.customExtraPaths}" + } + } + }, + "options": { + "env": { + "PATH": "${env:PATH}:${config:idf.customExtraPaths}" + } + }, + "problemMatcher": [ + { + "owner": "cpp", + "fileLocation": [ + "autoDetect", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "Set ESP-IDF Target", + "type": "shell", + "command": "${command:espIdf.setTarget}", + "problemMatcher": { + "owner": "cpp", + "fileLocation": [ + "autoDetect", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } + }, + { + "label": "Clean - Clean the project", + "type": "shell", + "command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py fullclean", + "windows": { + "command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py fullclean", + "options": { + "env": { + "PATH": "${env:PATH};${config:idf.customExtraPaths}" + } + } + }, + "options": { + "env": { + "PATH": "${env:PATH}:${config:idf.customExtraPaths}" + } + }, + "problemMatcher": [ + { + "owner": "cpp", + "fileLocation": [ + "autoDetect", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } + ] + }, + { + "label": "Flash - Flash the device", + "type": "shell", + "command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py -p ${config:idf.port} -b ${config:idf.flashBaudRate} flash", + "windows": { + "command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py flash -p ${config:idf.portWin} -b ${config:idf.flashBaudRate}", + "options": { + "env": { + "PATH": "${env:PATH};${config:idf.customExtraPaths}" + } + } + }, + "options": { + "env": { + "PATH": "${env:PATH}:${config:idf.customExtraPaths}" + } + }, + "problemMatcher": [ + { + "owner": "cpp", + "fileLocation": [ + "autoDetect", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } + ] + }, + { + "label": "Monitor: Start the monitor", + "type": "shell", + "command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py -p ${config:idf.port} monitor", + "windows": { + "command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py -p ${config:idf.portWin} monitor", + "options": { + "env": { + "PATH": "${env:PATH};${config:idf.customExtraPaths}" + } + } + }, + "options": { + "env": { + "PATH": "${env:PATH}:${config:idf.customExtraPaths}" + } + }, + "problemMatcher": [ + { + "owner": "cpp", + "fileLocation": [ + "autoDetect", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } + ], + "dependsOn": "Flash - Flash the device" + }, + { + "label": "OpenOCD: Start openOCD", + "type": "shell", + "presentation": { + "echo": true, + "reveal": "never", + "focus": false, + "panel": "new" + }, + "command": "openocd -s ${command:espIdf.getOpenOcdScriptValue} ${command:espIdf.getOpenOcdConfigs}", + "windows": { + "command": "openocd.exe -s ${command:espIdf.getOpenOcdScriptValue} ${command:espIdf.getOpenOcdConfigs}", + "options": { + "env": { + "PATH": "${env:PATH};${config:idf.customExtraPaths}" + } + } + }, + "options": { + "env": { + "PATH": "${env:PATH}:${config:idf.customExtraPaths}" + } + }, + "problemMatcher": { + "owner": "cpp", + "fileLocation": [ + "autoDetect", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } + }, + { + "label": "adapter", + "type": "shell", + "command": "${config:idf.pythonBinPath}", + "isBackground": true, + "options": { + "env": { + "PATH": "${env:PATH}:${config:idf.customExtraPaths}", + "PYTHONPATH": "${command:espIdf.getExtensionPath}/esp_debug_adapter/debug_adapter" + } + }, + "problemMatcher": { + "background": { + "beginsPattern": "\bDEBUG_ADAPTER_STARTED\b", + "endsPattern": "DEBUG_ADAPTER_READY2CONNECT", + "activeOnStart": true + }, + "pattern": { + "regexp": "(\\d+)-(\\d+)-(\\d+)\\s(\\d+):(\\d+):(\\d+),(\\d+)\\s-(.+)\\s(ERROR)", + "file": 8, + "line": 2, + "column": 3, + "severity": 4, + "message": 9 + } + }, + "args": [ + "${command:espIdf.getExtensionPath}/esp_debug_adapter/debug_adapter_main.py", + "-e", + "${workspaceFolder}/build/${command:espIdf.getProjectName}.elf", + "-s", + "$OPENOCD_SCRIPTS", + "-dn", + "esp32", + "-om", + "connect_to_instance", + "-t", + "xtensa-esp32-elf-" + + ], + "windows": { + "command": "${config:idf.pythonBinPathWin}", + "options": { + "env": { + "PATH": "${env:PATH};${config:idf.customExtraPaths}", + "PYTHONPATH": "${command:espIdf.getExtensionPath}/esp_debug_adapter/debug_adapter" + } + } + } + } + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b8ad270 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five 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) +project(ESP32-S3-Touch-LCD-4.3) diff --git a/README.md b/README.md new file mode 100644 index 0000000..7da61cb --- /dev/null +++ b/README.md @@ -0,0 +1,96 @@ +# Waveshare ESP32-S3-Touch-LCD-4.3 + +## Information + +- Orderlink: https://www.waveshare.com/esp32-s3-touch-lcd-4.3.htm +- Wiki: https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-4.3 + +## Monitor output + +``` +--- esp-idf-monitor 1.4.0 on /dev/cu.usbport 115200 --- +--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- +ESP-ROM:esp32s3-20210327 +Build:Mar 27 2021 +rst:0x15 (USB_UART_CHIP_RESET),boot:0x8 (SPI_FAST_FLASH_BOOT) +Saved PC:0x40378aca +0x40378aca: esp_cpu_wait_for_intr at /components/esp_hw_support/cpu.c:145 + +SPIWP:0xee +mode:DIO, clock div:1 +load:0x3fce3810,len:0x178c +load:0x403c9700,len:0x4 +load:0x403c9704,len:0xcbc +load:0x403cc700,len:0x2d9c +entry 0x403c9914 +I (26) boot: ESP-IDF v5.2.1-343-gf9163c6d43 2nd stage bootloader +I (27) boot: compile time Apr 19 2024 15:22:33 +I (27) boot: Multicore bootloader +I (31) boot: chip revision: v0.2 +I (35) boot.esp32s3: Boot SPI Speed : 80MHz +I (40) boot.esp32s3: SPI Mode : DIO +I (44) boot.esp32s3: SPI Flash Size : 8MB +I (49) boot: Enabling RNG early entropy source... +I (55) boot: Partition Table: +I (58) boot: ## Label Usage Type ST Offset Length +I (65) boot: 0 nvs WiFi data 01 02 00009000 00006000 +I (73) boot: 1 phy_init RF data 01 01 0000f000 00001000 +I (80) boot: 2 factory factory app 00 00 00010000 00100000 +I (88) boot: End of partition table +I (92) esp_image: segment 0: paddr=00010020 vaddr=3c050020 size=134a4h ( 79012) map +I (115) esp_image: segment 1: paddr=000234cc vaddr=3fc94500 size=03268h ( 12904) load +I (118) esp_image: segment 2: paddr=0002673c vaddr=40374000 size=098dch ( 39132) load +I (129) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=46ba4h (289700) map +I (181) esp_image: segment 4: paddr=00076bcc vaddr=4037d8dc size=06c10h ( 27664) load +I (195) boot: Loaded app from partition at offset 0x10000 +I (195) boot: Disabling RNG early entropy source... +I (206) cpu_start: Multicore app +I (206) octal_psram: vendor id : 0x0d (AP) +I (206) octal_psram: dev id : 0x02 (generation 3) +I (209) octal_psram: density : 0x03 (64 Mbit) +I (215) octal_psram: good-die : 0x01 (Pass) +I (220) octal_psram: Latency : 0x01 (Fixed) +I (225) octal_psram: VCC : 0x01 (3V) +I (230) octal_psram: SRF : 0x01 (Fast Refresh) +I (236) octal_psram: BurstType : 0x01 (Hybrid Wrap) +I (242) octal_psram: BurstLen : 0x01 (32 Byte) +I (247) octal_psram: Readlatency : 0x02 (10 cycles@Fixed) +I (254) octal_psram: DriveStrength: 0x00 (1/1) +I (259) MSPI Timing: PSRAM timing tuning index: 5 +I (264) esp_psram: Found 8MB PSRAM device +I (269) esp_psram: Speed: 80MHz +I (306) mmu_psram: Instructions copied and mapped to SPIRAM +I (320) mmu_psram: Read only data copied and mapped to SPIRAM +I (748) esp_psram: SPI SRAM memory test OK +I (757) cpu_start: Pro cpu start user code +I (757) cpu_start: cpu freq: 160000000 Hz +I (757) cpu_start: Application information: +I (760) cpu_start: Project name: ESP32-S3-LCD-4.3 +I (765) cpu_start: App version: 1 +I (770) cpu_start: Compile time: Apr 19 2024 15:22:19 +I (776) cpu_start: ELF file SHA256: 2a824ba9f... +I (781) cpu_start: ESP-IDF: v5.2.1-343-gf9163c6d43 +I (788) cpu_start: Min chip rev: v0.0 +I (792) cpu_start: Max chip rev: v0.99 +I (797) cpu_start: Chip rev: v0.2 +I (802) heap_init: Initializing. RAM available for dynamic allocation: +I (809) heap_init: At 3FCA0610 len 00049100 (292 KiB): RAM +I (815) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM +I (821) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM +I (827) heap_init: At 600FE010 len 00001FD8 (7 KiB): RTCRAM +I (834) esp_psram: Adding pool of 7744K of PSRAM memory to heap allocator +I (842) spi_flash: detected chip: gd +I (845) spi_flash: flash io: dio +I (850) sleep: Configure to isolate all GPIO pins in sleep state +I (856) sleep: Enable automatic switching of GPIO sleep configuration +I (864) main_task: Started on CPU0 +I (874) esp_psram: Reserving pool of 32K of internal memory for DMA/internal allocations +I (874) main_task: Calling app_main() +I (884) app: Initialize hardware +I (884) app: Install RGB LCD panel driver +I (914) app: Initialize LVGL library +I (914) app: Allocate separate LVGL draw buffers from PSRAM +I (914) app: Register display driver to LVGL +I (924) app: Install LVGL tick timer +I (924) app: LVGL demo +``` diff --git a/components/lvgl b/components/lvgl new file mode 160000 index 0000000..b09c793 --- /dev/null +++ b/components/lvgl @@ -0,0 +1 @@ +Subproject commit b09c79396773eead7586ee2099ea1bd18cf69e10 diff --git a/dependencies.lock b/dependencies.lock new file mode 100644 index 0000000..1639058 --- /dev/null +++ b/dependencies.lock @@ -0,0 +1,9 @@ +dependencies: + idf: + component_hash: null + source: + type: idf + version: 5.2.1 +manifest_hash: 0bba694ed2bf6b0b1a753eaa37f1fdf0a80b8cfdeb1e7df9dc1590302259f371 +target: esp32s3 +version: 1.0.0 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt new file mode 100644 index 0000000..025c949 --- /dev/null +++ b/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS main.c + REQUIRES esp_lcd lvgl + ) \ No newline at end of file diff --git a/main/main.c b/main/main.c new file mode 100644 index 0000000..2dd5bb1 --- /dev/null +++ b/main/main.c @@ -0,0 +1,255 @@ +#include +#include + +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_system.h" +#include "esp_timer.h" +#include "driver/ledc.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_panel_rgb.h" + +#include "lvgl.h" + +#include "sdkconfig.h" + +#define TAG "app" + +#define LVGL_TICK_PERIOD_MS 2 +#define LCD_PIXEL_CLOCK_HZ (12 * 1000 * 1000) + +#define LCD_H_RES 800 +#define LCD_V_RES 480 + +/* see https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-4.3 */ +#define PIN_NUM_PCLK (gpio_num_t) GPIO_NUM_7 +#define PIN_NUM_VSYNC (gpio_num_t) GPIO_NUM_3 +#define PIN_NUM_HSYNC (gpio_num_t) GPIO_NUM_46 +#define PIN_NUM_DE (gpio_num_t) GPIO_NUM_5 + +#define PIN_NUM_DATA0 (gpio_num_t) GPIO_NUM_14 /* B3 */ +#define PIN_NUM_DATA1 (gpio_num_t) GPIO_NUM_38 /* B4 */ +#define PIN_NUM_DATA2 (gpio_num_t) GPIO_NUM_18 /* B5 */ +#define PIN_NUM_DATA3 (gpio_num_t) GPIO_NUM_17 /* B6 */ +#define PIN_NUM_DATA4 (gpio_num_t) GPIO_NUM_10 /* B7 */ +#define PIN_NUM_DATA5 (gpio_num_t) GPIO_NUM_39 /* G2 */ +#define PIN_NUM_DATA6 (gpio_num_t) GPIO_NUM_0 /* G3 */ +#define PIN_NUM_DATA7 (gpio_num_t) GPIO_NUM_45 /* G4 */ +#define PIN_NUM_DATA8 (gpio_num_t) GPIO_NUM_48 /* G5 */ +#define PIN_NUM_DATA9 (gpio_num_t) GPIO_NUM_47 /* G6 */ +#define PIN_NUM_DATA10 (gpio_num_t) GPIO_NUM_21 /* G7 */ +#define PIN_NUM_DATA11 (gpio_num_t) GPIO_NUM_1 /* R3 */ +#define PIN_NUM_DATA12 (gpio_num_t) GPIO_NUM_2 /* R4 */ +#define PIN_NUM_DATA13 (gpio_num_t) GPIO_NUM_42 /* R5 */ +#define PIN_NUM_DATA14 (gpio_num_t) GPIO_NUM_41 /* R6 */ +#define PIN_NUM_DATA15 (gpio_num_t) GPIO_NUM_40 /* R7 */ + +typedef struct +{ + lv_obj_t *meter; + lv_meter_indicator_t *indicator; +} TMeter; + +TMeter *lvgl_demo(lv_disp_t *disp) +{ + static TMeter lvgl_meter; + + lv_obj_t *scr = lv_disp_get_scr_act(disp); + lv_obj_t *meter = lv_meter_create(scr); + + lv_obj_center(meter); + lv_obj_set_size(meter, 400, 400); + + lv_meter_scale_t *scale = lv_meter_add_scale(meter); + lv_meter_set_scale_range(meter, scale, 0, 60, 270, 135); + lv_meter_set_scale_ticks(meter, scale, 5, 5, 32, lv_palette_main(LV_PALETTE_GREY)); + + lv_meter_indicator_t *mi; + + mi = lv_meter_add_arc(meter, scale, 10, lv_palette_main(LV_PALETTE_BLUE), 0); + lv_meter_set_indicator_start_value(meter, mi, 0); + lv_meter_set_indicator_end_value(meter, mi, 20); + + mi = lv_meter_add_arc(meter, scale, 10, lv_palette_main(LV_PALETTE_GREEN), 0); + lv_meter_set_indicator_start_value(meter, mi, 20); + lv_meter_set_indicator_end_value(meter, mi, 40); + + mi = lv_meter_add_arc(meter, scale, 10, lv_palette_main(LV_PALETTE_ORANGE), 0); + lv_meter_set_indicator_start_value(meter, mi, 40); + lv_meter_set_indicator_end_value(meter, mi, 60); + + lvgl_meter.indicator = lv_meter_add_needle_line(meter, scale, 5, lv_palette_main(LV_PALETTE_PINK), 0); + lvgl_meter.meter = meter; + + return &lvgl_meter; +} + +void BacklightInit(void) +{ + ledc_timer_config_t ledTimer = { + .speed_mode = LEDC_LOW_SPEED_MODE, + .duty_resolution = LEDC_TIMER_12_BIT, + .timer_num = LEDC_TIMER_0, + .freq_hz = 5000, + .clk_cfg = LEDC_AUTO_CLK}; + + ledc_channel_config_t ledChannel = { + .gpio_num = GPIO_NUM_2, + .speed_mode = LEDC_LOW_SPEED_MODE, + .channel = LEDC_CHANNEL_0, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = LEDC_TIMER_0, + .duty = 0, + .hpoint = 0, + .flags.output_invert = 0}; + + ESP_ERROR_CHECK(ledc_timer_config(&ledTimer)); + ESP_ERROR_CHECK(ledc_channel_config(&ledChannel)); + ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191)); + ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0)); +} + +esp_lcd_panel_handle_t DisplayInit(void) +{ + ESP_LOGI(TAG, "Install RGB LCD panel driver"); + + esp_lcd_panel_handle_t panel_handle = NULL; + esp_lcd_rgb_panel_config_t panel_config = { + .clk_src = LCD_CLK_SRC_PLL160M, + .timings = { + .pclk_hz = LCD_PIXEL_CLOCK_HZ, + .h_res = LCD_H_RES, + .v_res = LCD_V_RES, + .hsync_pulse_width = 4, + .hsync_back_porch = 8, + .hsync_front_porch = 8, + .vsync_pulse_width = 4, + .vsync_back_porch = 8, + .vsync_front_porch = 8, + .flags.hsync_idle_low = true, + .flags.vsync_idle_low = true, + .flags.de_idle_high = false, + .flags.pclk_active_neg = true, + .flags.pclk_idle_high = false}, + .data_width = 16, + .sram_trans_align = 8, + .psram_trans_align = 64, + .hsync_gpio_num = PIN_NUM_HSYNC, + .vsync_gpio_num = PIN_NUM_VSYNC, + .de_gpio_num = PIN_NUM_DE, + .pclk_gpio_num = PIN_NUM_PCLK, + .data_gpio_nums = { + PIN_NUM_DATA0, + PIN_NUM_DATA1, + PIN_NUM_DATA2, + PIN_NUM_DATA3, + PIN_NUM_DATA4, + PIN_NUM_DATA5, + PIN_NUM_DATA6, + PIN_NUM_DATA7, + PIN_NUM_DATA8, + PIN_NUM_DATA9, + PIN_NUM_DATA10, + PIN_NUM_DATA11, + PIN_NUM_DATA12, + PIN_NUM_DATA13, + PIN_NUM_DATA14, + PIN_NUM_DATA15, + }, + .disp_gpio_num = GPIO_NUM_NC, + .flags.disp_active_low = 0, + .flags.fb_in_psram = true}; + ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); + + return panel_handle; +} + +static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) +{ + esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data; + int offsetx1 = area->x1; + int offsetx2 = area->x2; + int offsety1 = area->y1; + int offsety2 = area->y2; + + esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map); + lv_disp_flush_ready(drv); +} + +static void increase_lvgl_tick(void *arg) +{ + lv_tick_inc(LVGL_TICK_PERIOD_MS); +} + +void app_main(void) +{ + static esp_lcd_panel_handle_t panel_handle; + TMeter *lvgl_meter; + + ESP_LOGI(TAG, "Initialize hardware"); + BacklightInit(); + panel_handle = DisplayInit(); + + ESP_LOGI(TAG, "Initialize LVGL library"); + static lv_disp_draw_buf_t disp_buf; + static lv_disp_drv_t disp_drv; + lv_init(); + + ESP_LOGI(TAG, "Allocate separate LVGL draw buffers from PSRAM"); + void *buf1 = NULL; + void *buf2 = NULL; + + buf1 = heap_caps_malloc(LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); + assert(buf1); + buf2 = heap_caps_malloc(LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); + assert(buf2); + + lv_disp_draw_buf_init(&disp_buf, buf1, buf2, LCD_H_RES * 100); + + ESP_LOGI(TAG, "Register display driver to LVGL"); + lv_disp_drv_init(&disp_drv); + disp_drv.hor_res = LCD_H_RES; + disp_drv.ver_res = LCD_V_RES; + disp_drv.flush_cb = lvgl_flush_cb; + disp_drv.draw_buf = &disp_buf; + disp_drv.user_data = panel_handle; + disp_drv.full_refresh = false; + + lv_disp_t *disp = lv_disp_drv_register(&disp_drv); + + ESP_LOGI(TAG, "Install LVGL tick timer"); + const esp_timer_create_args_t lvgl_tick_timer_args = { + .callback = &increase_lvgl_tick, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "lvgl_tick", + .skip_unhandled_events = true}; + + esp_timer_handle_t lvgl_tick_timer = NULL; + ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, LVGL_TICK_PERIOD_MS * 1000)); + + ESP_LOGI(TAG, "LVGL demo"); + lvgl_meter = lvgl_demo(disp); + + uint8_t lastSec = 0; + struct timeval tv_now; + + while (42) + { + gettimeofday(&tv_now, NULL); + + if (lastSec != tv_now.tv_sec % 60) + { + lastSec = tv_now.tv_sec % 60; + lv_meter_set_indicator_value(lvgl_meter->meter, lvgl_meter->indicator, lastSec); + } + + vTaskDelay(pdMS_TO_TICKS(10)); + lv_timer_handler(); + } +} diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 0000000..f3b940e --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,8 @@ +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y +CONFIG_SPIRAM_RODATA=y +CONFIG_LV_USE_PERF_MONITOR=y \ No newline at end of file