mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/i80_lcd_psram_s3' into 'master'
lcd: i80 lcd can transfer framebuffer in PSRAM Closes IDFGH-6426 See merge request espressif/esp-idf!16548
This commit is contained in:
commit
6050388f51
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -151,6 +151,8 @@ typedef struct {
|
||||
int data_gpio_nums[SOC_LCD_I80_BUS_WIDTH]; /*!< GPIOs used for data lines */
|
||||
size_t bus_width; /*!< Number of data lines, 8 or 16 */
|
||||
size_t max_transfer_bytes; /*!< Maximum transfer size, this determines the length of internal DMA link */
|
||||
size_t psram_trans_align; /*!< DMA transfer alignment for data allocated from PSRAM */
|
||||
size_t sram_trans_align; /*!< DMA transfer alignment for data allocated from SRAM */
|
||||
} esp_lcd_i80_bus_config_t;
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/rtc.h" // for `rtc_clk_xtal_freq_get()`
|
||||
#include "soc/soc_memory_types.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "esp_private/gdma.h"
|
||||
@ -41,6 +42,9 @@ typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t;
|
||||
typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t;
|
||||
typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t;
|
||||
|
||||
// This function is located in ROM (also see esp_rom/${target}/ld/${target}.rom.ld)
|
||||
extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
|
||||
|
||||
static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size);
|
||||
static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size);
|
||||
static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io);
|
||||
@ -63,6 +67,8 @@ struct esp_lcd_i80_bus_t {
|
||||
uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer
|
||||
size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source
|
||||
gdma_channel_handle_t dma_chan; // DMA channel handle
|
||||
size_t psram_trans_align; // DMA transfer alignment for data allocated from PSRAM
|
||||
size_t sram_trans_align; // DMA transfer alignment for data allocated from SRAM
|
||||
lcd_i80_trans_descriptor_t *cur_trans; // Current transaction
|
||||
lcd_panel_io_i80_t *cur_device; // Current working device
|
||||
LIST_HEAD(i80_device_list, lcd_panel_io_i80_t) device_list; // Head of i80 device list
|
||||
@ -120,11 +126,11 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
|
||||
ESP_GOTO_ON_FALSE(bus_config && ret_bus, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
size_t num_dma_nodes = bus_config->max_transfer_bytes / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1;
|
||||
// DMA descriptors must be placed in internal SRAM
|
||||
bus = heap_caps_calloc(1, sizeof(esp_lcd_i80_bus_t) + num_dma_nodes * sizeof(dma_descriptor_t), MALLOC_CAP_DMA);
|
||||
bus = heap_caps_calloc(1, sizeof(esp_lcd_i80_bus_t) + num_dma_nodes * sizeof(dma_descriptor_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
|
||||
ESP_GOTO_ON_FALSE(bus, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 bus");
|
||||
bus->num_dma_nodes = num_dma_nodes;
|
||||
bus->bus_id = -1;
|
||||
bus->format_buffer = heap_caps_calloc(1, CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE, MALLOC_CAP_DMA);
|
||||
bus->format_buffer = heap_caps_calloc(1, CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
|
||||
ESP_GOTO_ON_FALSE(bus->format_buffer, ESP_ERR_NO_MEM, err, TAG, "no mem for format buffer");
|
||||
// register to platform
|
||||
int bus_id = lcd_com_register_device(LCD_COM_DEVICE_TYPE_I80, bus);
|
||||
@ -151,6 +157,8 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
|
||||
lcd_ll_enable_interrupt(bus->hal.dev, LCD_LL_EVENT_TRANS_DONE, false); // disable all interrupts
|
||||
lcd_ll_clear_interrupt_status(bus->hal.dev, UINT32_MAX); // clear pending interrupt
|
||||
// install DMA service
|
||||
bus->psram_trans_align = bus_config->psram_trans_align;
|
||||
bus->sram_trans_align = bus_config->sram_trans_align;
|
||||
ret = lcd_i80_init_dma_link(bus);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "install DMA failed");
|
||||
// enable 8080 mode and set bus width
|
||||
@ -436,6 +444,12 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
|
||||
trans_desc->data_length = color_size;
|
||||
trans_desc->trans_done_cb = i80_device->on_color_trans_done;
|
||||
trans_desc->user_ctx = i80_device->user_ctx;
|
||||
|
||||
if (esp_ptr_external_ram(color)) {
|
||||
// flush framebuffer from cache to the physical PSRAM
|
||||
Cache_WriteBack_Addr((uint32_t)color, color_size);
|
||||
}
|
||||
|
||||
// send transaction to trans_queue
|
||||
xQueueSend(i80_device->trans_queue, &trans_desc, portMAX_DELAY);
|
||||
i80_device->num_trans_inflight++;
|
||||
@ -489,6 +503,12 @@ static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus)
|
||||
.owner_check = true
|
||||
};
|
||||
gdma_apply_strategy(bus->dma_chan, &strategy_config);
|
||||
// set DMA transfer ability
|
||||
gdma_transfer_ability_t ability = {
|
||||
.psram_trans_align = bus->psram_trans_align,
|
||||
.sram_trans_align = bus->sram_trans_align,
|
||||
};
|
||||
gdma_set_transfer_ability(bus->dma_chan, &ability);
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (bus->dma_chan) {
|
||||
|
@ -408,157 +408,6 @@ TEST_CASE("lcd panel with i80 interface (st7789, 8bits)", "[lcd]")
|
||||
#undef TEST_IMG_SIZE
|
||||
}
|
||||
|
||||
// The following test shows a porting example of LVGL GUI library
|
||||
// To run the LVGL tests, you need to clone the LVGL library into components directory firstly
|
||||
#if CONFIG_LV_USE_USER_DATA
|
||||
#include "test_lvgl_port.h"
|
||||
|
||||
static bool notify_lvgl_ready_to_flush(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
lv_disp_t *disp = *(lv_disp_t **)user_ctx;
|
||||
lv_disp_flush_ready(&disp->driver);
|
||||
return false;
|
||||
}
|
||||
|
||||
TEST_CASE("lvgl gui with i80 interface (st7789, 8bits)", "[lcd][lvgl][ignore]")
|
||||
{
|
||||
// initialize LVGL graphics library
|
||||
lv_disp_t *disp = NULL;
|
||||
lv_init();
|
||||
|
||||
gpio_config_t bk_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << TEST_LCD_BK_LIGHT_GPIO
|
||||
};
|
||||
TEST_ESP_OK(gpio_config(&bk_gpio_config));
|
||||
|
||||
esp_lcd_i80_bus_handle_t i80_bus = NULL;
|
||||
esp_lcd_i80_bus_config_t bus_config = {
|
||||
.dc_gpio_num = TEST_LCD_DC_GPIO,
|
||||
.wr_gpio_num = TEST_LCD_PCLK_GPIO,
|
||||
.data_gpio_nums = {
|
||||
TEST_LCD_DATA0_GPIO,
|
||||
TEST_LCD_DATA1_GPIO,
|
||||
TEST_LCD_DATA2_GPIO,
|
||||
TEST_LCD_DATA3_GPIO,
|
||||
TEST_LCD_DATA4_GPIO,
|
||||
TEST_LCD_DATA5_GPIO,
|
||||
TEST_LCD_DATA6_GPIO,
|
||||
TEST_LCD_DATA7_GPIO,
|
||||
},
|
||||
.bus_width = 8,
|
||||
.max_transfer_bytes = TEST_LCD_H_RES * 40 * sizeof(uint16_t)
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
esp_lcd_panel_io_i80_config_t io_config = {
|
||||
.cs_gpio_num = TEST_LCD_CS_GPIO,
|
||||
.pclk_hz = 10000000, // 10MHz
|
||||
.trans_queue_depth = 10,
|
||||
.dc_levels = {
|
||||
.dc_idle_level = 0,
|
||||
.dc_cmd_level = 0,
|
||||
.dc_dummy_level = 0,
|
||||
.dc_data_level = 1,
|
||||
},
|
||||
.flags = {
|
||||
.swap_color_bytes = 1,
|
||||
},
|
||||
.on_color_trans_done = notify_lvgl_ready_to_flush,
|
||||
.user_ctx = &disp,
|
||||
.lcd_cmd_bits = 8,
|
||||
.lcd_param_bits = 8,
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
|
||||
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = TEST_LCD_RST_GPIO,
|
||||
.color_space = ESP_LCD_COLOR_SPACE_RGB,
|
||||
.bits_per_pixel = 16,
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
|
||||
|
||||
// turn off backlight
|
||||
gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0);
|
||||
esp_lcd_panel_reset(panel_handle);
|
||||
esp_lcd_panel_init(panel_handle);
|
||||
esp_lcd_panel_invert_color(panel_handle, true);
|
||||
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
|
||||
esp_lcd_panel_set_gap(panel_handle, 0, 20);
|
||||
// turn on backlight
|
||||
gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
|
||||
|
||||
test_lvgl_task_loop(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES, &disp);
|
||||
}
|
||||
|
||||
#define TEST_NT35510_DATA_WIDTH (8) // change this to 16 when NT35510 is configured to 16bit in length
|
||||
TEST_CASE("lvgl gui with i80 interface (nt35510, 8/16bits)", "[lcd][lvgl][ignore]")
|
||||
{
|
||||
// initialize LVGL graphics library
|
||||
lv_disp_t *disp = NULL;
|
||||
lv_init();
|
||||
|
||||
esp_lcd_i80_bus_handle_t i80_bus = NULL;
|
||||
esp_lcd_i80_bus_config_t bus_config = {
|
||||
.dc_gpio_num = TEST_LCD_DC_GPIO,
|
||||
.wr_gpio_num = TEST_LCD_PCLK_GPIO,
|
||||
.data_gpio_nums = {
|
||||
TEST_LCD_DATA0_GPIO,
|
||||
TEST_LCD_DATA1_GPIO,
|
||||
TEST_LCD_DATA2_GPIO,
|
||||
TEST_LCD_DATA3_GPIO,
|
||||
TEST_LCD_DATA4_GPIO,
|
||||
TEST_LCD_DATA5_GPIO,
|
||||
TEST_LCD_DATA6_GPIO,
|
||||
TEST_LCD_DATA7_GPIO,
|
||||
TEST_LCD_DATA8_GPIO,
|
||||
TEST_LCD_DATA9_GPIO,
|
||||
TEST_LCD_DATA10_GPIO,
|
||||
TEST_LCD_DATA11_GPIO,
|
||||
TEST_LCD_DATA12_GPIO,
|
||||
TEST_LCD_DATA13_GPIO,
|
||||
TEST_LCD_DATA14_GPIO,
|
||||
TEST_LCD_DATA15_GPIO,
|
||||
},
|
||||
.bus_width = TEST_NT35510_DATA_WIDTH,
|
||||
.max_transfer_bytes = TEST_LCD_H_RES * 40 * sizeof(uint16_t)
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
esp_lcd_panel_io_i80_config_t io_config = {
|
||||
.cs_gpio_num = TEST_LCD_CS_GPIO,
|
||||
.pclk_hz = 10000000, // 10MHz
|
||||
.trans_queue_depth = 4,
|
||||
.dc_levels = {
|
||||
.dc_idle_level = 0,
|
||||
.dc_cmd_level = 0,
|
||||
.dc_dummy_level = 0,
|
||||
.dc_data_level = 1,
|
||||
},
|
||||
.on_color_trans_done = notify_lvgl_ready_to_flush,
|
||||
.user_ctx = &disp,
|
||||
.lcd_cmd_bits = 16,
|
||||
.lcd_param_bits = 16,
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
|
||||
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = -1,
|
||||
.color_space = ESP_LCD_COLOR_SPACE_RGB,
|
||||
.bits_per_pixel = 16,
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
|
||||
|
||||
esp_lcd_panel_reset(panel_handle);
|
||||
esp_lcd_panel_init(panel_handle);
|
||||
esp_lcd_panel_swap_xy(panel_handle, true);
|
||||
esp_lcd_panel_mirror(panel_handle, true, false);
|
||||
|
||||
test_lvgl_task_loop(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES, &disp);
|
||||
}
|
||||
#endif // CONFIG_LV_USE_USER_DATA
|
||||
#endif // SOC_LCD_I80_SUPPORTED
|
||||
|
||||
#if SOC_I2S_LCD_I80_VARIANT
|
||||
|
@ -23,7 +23,7 @@ Application Example
|
||||
LCD examples are located under: :example:`peripherals/lcd`:
|
||||
|
||||
* Jpeg decoding and LCD display - :example:`peripherals/lcd/tjpgd`
|
||||
* LVGL porting and animation UI - :example:`peripherals/lcd/lvgl`
|
||||
* i80 controller based LCD and LVGL animation UI - :example:`peripherals/lcd/i80_controller`
|
||||
* GC9A01 user customized driver and dash board UI - :example:`peripherals/lcd/gc9a01`
|
||||
|
||||
API Reference
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
`esp_lcd` allows user to add their own panel drivers in the project scope (i.e. panel driver can live outside of esp-idf), so that the upper layer code like LVGL porting code can be reused without any modifications, as long as user-implemented panel driver follows the interface defined in the `esp_lcd` component.
|
||||
|
||||
This example shows how to add the GC9A01 driver in the project folder but still use the API provided by `esp_lcd` component. As GC9A01 is famous in the form of a circular screen, this example will draw a fancy dash board with the LVGL library. For more information about porting the LVGL library, you can also refer to another [lvgl porting example](../lvgl/README.md).
|
||||
This example shows how to add the GC9A01 driver in the project folder but still use the API provided by `esp_lcd` component. As GC9A01 is famous in the form of a circular screen, this example will draw a fancy dash board with the LVGL library. For more information about porting the LVGL library, you can also refer to another [lvgl porting example](../i80_controller/README.md).
|
||||
|
||||
## How to use the example
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(lcd_lvgl)
|
||||
project(i80_controller)
|
||||
|
||||
# As the upstream LVGL library has build warnings in esp-idf build system, this is only for temporarily workaround
|
||||
# Will remove this workaround when upstream LVGL fixes the warnings in the next release
|
@ -1,12 +1,12 @@
|
||||
| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- |
|
||||
# LVGL porting example
|
||||
# LVGL porting example (based on i80 interfaced LCD controller)
|
||||
|
||||
LVGL is an open-source graphics library for creating modern GUIs. It has plenty of built-in graphical elements with low memory footprint, which is friendly for embedded GUI applications.
|
||||
|
||||
This example can be taken as a skeleton of porting the LVGL library onto the `esp_lcd` driver layer. **Note** that, this example only focuses on the display interface, regardless of the input device driver.
|
||||
|
||||
The whole porting code is located in [this main file](main/lvgl_example_main.c), and the UI demo code is located in [another single file](main/lvgl_demo_ui.c).
|
||||
The whole porting code is located in [i80_controller_example_main.c](main/i80_controller_example_main.c), and the UI demo code is located in [lvgl_demo_ui.c](main/lvgl_demo_ui.c).
|
||||
|
||||
The UI will display two images (one Espressif logo and another Espressif text), which have been converted into C arrays by the [online converting tool](https://lvgl.io/tools/imageconverter), and will be compiled directly into application binary.
|
||||
|
||||
@ -49,11 +49,17 @@ The connection between ESP Board and the LCD is as follows:
|
||||
└─────────────┘ └────────────────┘
|
||||
```
|
||||
|
||||
The GPIO number used by this example can be changed in [lvgl_example_main.c](main/lvgl_example_main.c).
|
||||
Especially, please pay attention to the level used to turn on the LCD backlight, some LCD module needs a low level to turn it on, while others take a high level. You can change the backlight level macro `EXAMPLE_LCD_BK_LIGHT_ON_LEVEL` in [lvgl_example_main.c](main/lvgl_example_main.c).
|
||||
The GPIO number used by this example can be changed in [i80_controller_example_main.c](main/i80_controller_example_main.c).
|
||||
Especially, please pay attention to the binary signal level used to turn the LCD backlight on, some LCD modules need a low level to turn it on, while others require a high level. You can change the backlight level macro `EXAMPLE_LCD_BK_LIGHT_ON_LEVEL` in [i80_controller_example_main.c](main/i80_controller_example_main.c).
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Run `idf.py set-target <target-name>` to select one supported target that can run this example. This step will also apply the default Kconfig configurations into the `sdkconfig` file.
|
||||
|
||||
Run `idf.py menuconfig` to open a terminal UI where you can tune specific configuration for this example in the `Example Configuration` menu.
|
||||
|
||||
* `Allocate color data from PSRAM`: Select this option if you want to allocate the LVGL draw buffers from PSRAM.
|
||||
|
||||
Run `idf.py -p PORT build flash monitor` to build, flash and monitor the project. A fancy animation will show up on the LCD as expected.
|
||||
|
||||
The first time you run `idf.py` for the example will cost extra time as the build system needs to address the component dependencies and downloads the missing components from registry into `managed_components` folder.
|
||||
@ -80,4 +86,8 @@ I (558) example: Display LVGL animation
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* Can't get a stable UI when `EXAMPLE_LCD_I80_COLOR_IN_PSRAM` is enabled.
|
||||
|
||||
This is because of the limited PSRAM bandwidth, compared to the internal SRAM. You can either decrease the PCLK clock `EXAMPLE_LCD_PIXEL_CLOCK_HZ` in [i80_controller_example_main.c](main/i80_controller_example_main.c) or increase the PSRAM working frequency `SPIRAM_SPEED` from the KConfig (e.g. **ESP32S3-Specific** -> **Set RAM clock speed**) or decrease the FPS in LVGL configuration. For illustration, this example has set the refresh period to 100ms in the default sdkconfig file.
|
||||
|
||||
For any technical queries, please open an [issue] (https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
@ -0,0 +1,4 @@
|
||||
file(GLOB_RECURSE IMAGE_SOURCES images/*.c)
|
||||
|
||||
idf_component_register(SRCS "i80_controller_example_main.c" "lvgl_demo_ui.c" ${IMAGE_SOURCES}
|
||||
INCLUDE_DIRS ".")
|
@ -0,0 +1,11 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_LCD_I80_COLOR_IN_PSRAM
|
||||
bool "Allocate color data from PSRAM"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
default y
|
||||
help
|
||||
Enable this option if you wish to allocate the color buffer used by LVGL from PSRAM.
|
||||
Unmatched PSRAM band width with LCD requirement can lead to blurred image display.
|
||||
|
||||
endmenu
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
@ -21,22 +21,28 @@ static const char *TAG = "example";
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////// Please update the following configuration according to your LCD spec //////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
|
||||
// PCLK frequency can't go too high as the limitation of PSRAM bandwidth
|
||||
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (2 * 1000 * 1000)
|
||||
#else
|
||||
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (10 * 1000 * 1000)
|
||||
#endif // CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
|
||||
|
||||
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1
|
||||
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
|
||||
#define EXAMPLE_PIN_NUM_DATA0 19
|
||||
#define EXAMPLE_PIN_NUM_DATA1 21
|
||||
#define EXAMPLE_PIN_NUM_DATA2 0
|
||||
#define EXAMPLE_PIN_NUM_DATA3 22
|
||||
#define EXAMPLE_PIN_NUM_DATA4 23
|
||||
#define EXAMPLE_PIN_NUM_DATA5 33
|
||||
#define EXAMPLE_PIN_NUM_DATA6 32
|
||||
#define EXAMPLE_PIN_NUM_DATA7 27
|
||||
#define EXAMPLE_PIN_NUM_PCLK 18
|
||||
#define EXAMPLE_PIN_NUM_CS 4
|
||||
#define EXAMPLE_PIN_NUM_DC 5
|
||||
#define EXAMPLE_PIN_NUM_RST -1
|
||||
#define EXAMPLE_PIN_NUM_BK_LIGHT 2
|
||||
#define EXAMPLE_PIN_NUM_DATA0 6
|
||||
#define EXAMPLE_PIN_NUM_DATA1 7
|
||||
#define EXAMPLE_PIN_NUM_DATA2 8
|
||||
#define EXAMPLE_PIN_NUM_DATA3 9
|
||||
#define EXAMPLE_PIN_NUM_DATA4 10
|
||||
#define EXAMPLE_PIN_NUM_DATA5 11
|
||||
#define EXAMPLE_PIN_NUM_DATA6 12
|
||||
#define EXAMPLE_PIN_NUM_DATA7 13
|
||||
#define EXAMPLE_PIN_NUM_PCLK 5
|
||||
#define EXAMPLE_PIN_NUM_CS 3
|
||||
#define EXAMPLE_PIN_NUM_DC 4
|
||||
#define EXAMPLE_PIN_NUM_RST 2
|
||||
#define EXAMPLE_PIN_NUM_BK_LIGHT 1
|
||||
|
||||
// The pixel number in horizontal and vertical
|
||||
#define EXAMPLE_LCD_H_RES 240
|
||||
@ -47,6 +53,9 @@ static const char *TAG = "example";
|
||||
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||
|
||||
// Supported alignment: 16, 32, 64. A higher alignment can enables higher burst transfer size, thus a higher i80 bus throughput.
|
||||
#define EXAMPLE_PSRAM_DATA_ALIGNMENT 64
|
||||
|
||||
extern void example_lvgl_demo_ui(lv_obj_t *scr);
|
||||
|
||||
static bool example_notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
|
||||
@ -102,7 +111,9 @@ void app_main(void)
|
||||
EXAMPLE_PIN_NUM_DATA7,
|
||||
},
|
||||
.bus_width = 8,
|
||||
.max_transfer_bytes = EXAMPLE_LCD_H_RES * 40 * sizeof(uint16_t)
|
||||
.max_transfer_bytes = EXAMPLE_LCD_H_RES * 100 * sizeof(uint16_t),
|
||||
.psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
|
||||
.sram_trans_align = 4,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
@ -145,12 +156,23 @@ void app_main(void)
|
||||
lv_init();
|
||||
// alloc draw buffers used by LVGL
|
||||
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
|
||||
lv_color_t *buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
lv_color_t *buf1 = NULL;
|
||||
lv_color_t *buf2 = NULL;
|
||||
#if CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
|
||||
buf1 = heap_caps_aligned_alloc(EXAMPLE_PSRAM_DATA_ALIGNMENT, EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
#else
|
||||
buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
#endif
|
||||
assert(buf1);
|
||||
lv_color_t *buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
#if CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
|
||||
buf2 = heap_caps_aligned_alloc(EXAMPLE_PSRAM_DATA_ALIGNMENT, EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
#else
|
||||
buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
#endif
|
||||
assert(buf2);
|
||||
ESP_LOGI(TAG, "buf1@%p, buf2@%p", buf1, buf2);
|
||||
// initialize LVGL draw buffers
|
||||
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * 20);
|
||||
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * 100);
|
||||
|
||||
ESP_LOGI(TAG, "Register display driver to LVGL");
|
||||
lv_disp_drv_init(&disp_drv);
|
@ -1,3 +1,3 @@
|
||||
dependencies:
|
||||
idf: ">=4.4"
|
||||
lvgl/lvgl: "==8.0.2"
|
||||
lvgl/lvgl: "~8.0.2"
|
@ -1,3 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
// NOTE: The logo in this file is registered trademark by Espressif Systems (Shanghai) CO LTD.
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
@ -1,3 +1,8 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include "lvgl.h"
|
||||
|
||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
@ -1,3 +1,5 @@
|
||||
CONFIG_LV_MEM_CUSTOM=y
|
||||
CONFIG_LV_MEMCPY_MEMSET_STD=y
|
||||
CONFIG_LV_USE_PERF_MONITOR=y
|
||||
CONFIG_LV_USE_USER_DATA=y
|
||||
CONFIG_LV_COLOR_16_SWAP=y
|
@ -0,0 +1,4 @@
|
||||
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
|
||||
CONFIG_SPIRAM_SPEED_80M=y
|
||||
# Can't set the FPS too high due to the limitation of PSRAM bandwidth
|
||||
CONFIG_LV_DISP_DEF_REFR_PERIOD=100
|
@ -1,4 +0,0 @@
|
||||
file(GLOB_RECURSE IMAGE_SOURCES images/*.c)
|
||||
|
||||
idf_component_register(SRCS "lvgl_example_main.c" "lvgl_demo_ui.c" ${IMAGE_SOURCES}
|
||||
INCLUDE_DIRS ".")
|
Loading…
Reference in New Issue
Block a user