diff --git a/.vscode/settings.json b/.vscode/settings.json index 191e7bc..9406151 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "idf.currentSetup": "/Users/moyyang/esp/v5.5.2/esp-idf", "idf.flashType": "UART", - "idf.port": "/dev/tty.wchusbserial5B0B0251771", + "idf.port": "/dev/tty.usbserial-140", "idf.openOcdConfigs": [ "board/esp32s3-builtin.cfg" ], diff --git a/components/lcd/CMakeLists.txt b/components/lcd/CMakeLists.txt new file mode 100644 index 0000000..952d0ed --- /dev/null +++ b/components/lcd/CMakeLists.txt @@ -0,0 +1,18 @@ +idf_component_register( + SRCS + "src/lcd_demo.c" + "src/st7789p3.c" + "src/lcd_decode_image.c" + "src/lcd_pretty_effect.c" + INCLUDE_DIRS + "include" + PRIV_INCLUDE_DIRS + "internal" + REQUIRES + driver + esp_driver_gpio + esp_driver_spi + espressif__esp_jpeg + EMBED_FILES + "assets/lcd_demo.jpg" +) diff --git a/components/lcd/assets/lcd_demo.jpg b/components/lcd/assets/lcd_demo.jpg new file mode 100644 index 0000000..cacad09 Binary files /dev/null and b/components/lcd/assets/lcd_demo.jpg differ diff --git a/components/lcd/include/lcd.h b/components/lcd/include/lcd.h new file mode 100644 index 0000000..ec6bf03 --- /dev/null +++ b/components/lcd/include/lcd.h @@ -0,0 +1,15 @@ +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +esp_err_t lcd_module_init(void); +esp_err_t lcd_module_start_demo(void); +void lcd_module_deinit(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/lcd/internal/lcd_decode_image.h b/components/lcd/internal/lcd_decode_image.h new file mode 100644 index 0000000..269013c --- /dev/null +++ b/components/lcd/internal/lcd_decode_image.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +#include "esp_err.h" + +#define PLATFORM_LCD_DEMO_IMAGE_W 320 +#define PLATFORM_LCD_DEMO_IMAGE_H 240 + +esp_err_t platform_lcd_decode_image(uint16_t **pixels); diff --git a/components/lcd/internal/lcd_pretty_effect.h b/components/lcd/internal/lcd_pretty_effect.h new file mode 100644 index 0000000..0422b80 --- /dev/null +++ b/components/lcd/internal/lcd_pretty_effect.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +#include "esp_err.h" + +void platform_lcd_pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect); +esp_err_t platform_lcd_pretty_effect_init(void); diff --git a/components/lcd/internal/st7789p3.h b/components/lcd/internal/st7789p3.h new file mode 100644 index 0000000..a9ce39e --- /dev/null +++ b/components/lcd/internal/st7789p3.h @@ -0,0 +1,89 @@ +#pragma once + +#include +#include +#include + +#include "driver/spi_master.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st7789p3_panel_t *st7789p3_handle_t; + +#define ST7789P3_MADCTL_MY 0x80 +#define ST7789P3_MADCTL_MX 0x40 +#define ST7789P3_MADCTL_MV 0x20 +#define ST7789P3_MADCTL_ML 0x10 +#define ST7789P3_MADCTL_BGR 0x08 +#define ST7789P3_MADCTL_MH 0x04 + +typedef struct { + spi_host_device_t spi_host; + int pin_mosi; + int pin_miso; + int pin_sclk; + int pin_cs; + int pin_dc; + int pin_rst; + int pin_bckl; + uint32_t pclk_hz; + uint8_t spi_mode; + int queue_size; + size_t max_transfer_sz; + uint16_t h_res; + uint16_t v_res; + uint8_t madctl_val; + bool invert_color; + int backlight_on_level; + bool init_spi_bus; +} st7789p3_config_t; + +#define ST7789P3_CONFIG_DEFAULT() \ + { \ + .spi_host = SPI2_HOST, \ + .pin_mosi = -1, \ + .pin_miso = -1, \ + .pin_sclk = -1, \ + .pin_cs = -1, \ + .pin_dc = -1, \ + .pin_rst = -1, \ + .pin_bckl = -1, \ + .pclk_hz = 10 * 1000 * 1000, \ + .spi_mode = 0, \ + .queue_size = 7, \ + .max_transfer_sz = 0, \ + .h_res = 320, \ + .v_res = 240, \ + .madctl_val = ST7789P3_MADCTL_MX | ST7789P3_MADCTL_MV, \ + .invert_color = false, \ + .backlight_on_level = 1, \ + .init_spi_bus = true, \ + } + +esp_err_t st7789p3_new_panel(const st7789p3_config_t *config, st7789p3_handle_t *ret_panel); +esp_err_t st7789p3_del(st7789p3_handle_t panel); + +esp_err_t st7789p3_reset(st7789p3_handle_t panel); +esp_err_t st7789p3_init(st7789p3_handle_t panel); + +esp_err_t st7789p3_set_backlight(st7789p3_handle_t panel, bool on); +esp_err_t st7789p3_set_madctl(st7789p3_handle_t panel, uint8_t madctl_val); +esp_err_t st7789p3_set_invert(st7789p3_handle_t panel, bool invert_color); + +esp_err_t st7789p3_set_window( + st7789p3_handle_t panel, uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end); +esp_err_t st7789p3_draw_bitmap(st7789p3_handle_t panel, + uint16_t x_start, + uint16_t y_start, + uint16_t x_end, + uint16_t y_end, + const uint16_t *color_data); + +esp_err_t st7789p3_fill_color(st7789p3_handle_t panel, uint16_t color); + +#ifdef __cplusplus +} +#endif diff --git a/components/lcd/src/lcd_decode_image.c b/components/lcd/src/lcd_decode_image.c new file mode 100644 index 0000000..c9cf23e --- /dev/null +++ b/components/lcd/src/lcd_decode_image.c @@ -0,0 +1,47 @@ +#include "lcd_decode_image.h" + +#include + +#include "esp_check.h" +#include "esp_log.h" +#include "jpeg_decoder.h" + +static const char *TAG = "lcd_image_dec"; + +extern const uint8_t lcd_demo_jpg_start[] asm("_binary_lcd_demo_jpg_start"); +extern const uint8_t lcd_demo_jpg_end[] asm("_binary_lcd_demo_jpg_end"); + +esp_err_t platform_lcd_decode_image(uint16_t **pixels) +{ + ESP_RETURN_ON_FALSE(pixels != NULL, ESP_ERR_INVALID_ARG, TAG, "pixels pointer is null"); + *pixels = NULL; + + esp_err_t ret = ESP_OK; + + *pixels = calloc(PLATFORM_LCD_DEMO_IMAGE_W * PLATFORM_LCD_DEMO_IMAGE_H, sizeof(uint16_t)); + ESP_GOTO_ON_FALSE(*pixels != NULL, ESP_ERR_NO_MEM, err, TAG, "alloc image buffer failed"); + + esp_jpeg_image_cfg_t jpeg_cfg = { + .indata = (uint8_t *)lcd_demo_jpg_start, + .indata_size = lcd_demo_jpg_end - lcd_demo_jpg_start, + .outbuf = (uint8_t *)(*pixels), + .outbuf_size = PLATFORM_LCD_DEMO_IMAGE_W * PLATFORM_LCD_DEMO_IMAGE_H * sizeof(uint16_t), + .out_format = JPEG_IMAGE_FORMAT_RGB565, + .out_scale = JPEG_IMAGE_SCALE_0, + .flags = { + .swap_color_bytes = 1, + }, + }; + + esp_jpeg_image_output_t out_img = {0}; + ret = esp_jpeg_decode(&jpeg_cfg, &out_img); + ESP_GOTO_ON_ERROR(ret, err, TAG, "jpeg decode failed"); + + ESP_LOGI(TAG, "lcd demo image decoded: %d x %d", out_img.width, out_img.height); + return ESP_OK; + +err: + free(*pixels); + *pixels = NULL; + return ret; +} diff --git a/components/lcd/src/lcd_demo.c b/components/lcd/src/lcd_demo.c new file mode 100644 index 0000000..b27565e --- /dev/null +++ b/components/lcd/src/lcd_demo.c @@ -0,0 +1,200 @@ +#include "lcd.h" + +#include + +#include "esp_check.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "lcd_pretty_effect.h" +#include "sdkconfig.h" +#include "st7789p3.h" + +static const char *TAG = "lcd_demo"; + +#define ST7789_SPI_HOST SPI2_HOST +#define LCD_DEMO_H_RES 320 +#define LCD_DEMO_V_RES 240 +#define LCD_DEMO_PARALLEL_LINES 16 +#define LCD_DEMO_TASK_STACK_SIZE (6 * 1024) +#define LCD_DEMO_TASK_PRIORITY (tskIDLE_PRIORITY + 1) +#define LCD_DEMO_TASK_CORE_ID 1 + +#ifndef CONFIG_TQ_SCREEN_SPI_MODE +#define CONFIG_TQ_SCREEN_SPI_MODE 0 +#endif + +#ifndef CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH +#define CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH 1 +#endif + +#if CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH +#define ST7789_BACKLIGHT_ON_LEVEL 1 +#else +#define ST7789_BACKLIGHT_ON_LEVEL 0 +#endif + +typedef struct { + st7789p3_handle_t panel; + TaskHandle_t demo_task; + bool initialized; +} lcd_state_t; + +static lcd_state_t s_lcd; + +static int resolve_reset_pin(void) +{ + if (CONFIG_TQ_SCREEN_RESET_PIN >= 0) { + return CONFIG_TQ_SCREEN_RESET_PIN; + } + return CONFIG_TQ_SCREEN_BACKLIGHT_PIN; +} + +static void lcd_demo_task(void *arg) +{ + st7789p3_handle_t panel = (st7789p3_handle_t)arg; + uint16_t *lines[2] = {0}; + const size_t line_buffer_bytes = LCD_DEMO_H_RES * LCD_DEMO_PARALLEL_LINES * sizeof(uint16_t); + int frame = 0; + int draw_buffer_index = 0; + + esp_err_t err = platform_lcd_pretty_effect_init(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "pretty effect init failed: %s", esp_err_to_name(err)); + goto exit; + } + + for (int i = 0; i < 2; i++) { + lines[i] = heap_caps_malloc(line_buffer_bytes, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + if (lines[i] == NULL) { + lines[i] = heap_caps_malloc(line_buffer_bytes, MALLOC_CAP_8BIT); + } + if (lines[i] == NULL) { + ESP_LOGE(TAG, "lcd demo line buffer alloc failed"); + goto exit; + } + } + + ESP_LOGI(TAG, "ST7789P3 pretty effect demo started"); + while (true) { + frame++; + for (int y = 0; y < LCD_DEMO_V_RES; y += LCD_DEMO_PARALLEL_LINES) { + int lines_to_draw = LCD_DEMO_V_RES - y; + if (lines_to_draw > LCD_DEMO_PARALLEL_LINES) { + lines_to_draw = LCD_DEMO_PARALLEL_LINES; + } + + platform_lcd_pretty_effect_calc_lines(lines[draw_buffer_index], y, frame, lines_to_draw); + err = st7789p3_draw_bitmap(panel, 0, y, LCD_DEMO_H_RES, y + lines_to_draw, lines[draw_buffer_index]); + if (err != ESP_OK) { + ESP_LOGE(TAG, "lcd demo draw failed: %s", esp_err_to_name(err)); + goto exit; + } + + draw_buffer_index ^= 1; + vTaskDelay(pdMS_TO_TICKS(1)); + } + } + +exit: + if (lines[0] != NULL) { + heap_caps_free(lines[0]); + } + if (lines[1] != NULL) { + heap_caps_free(lines[1]); + } + s_lcd.demo_task = NULL; + vTaskDelete(NULL); +} + +void lcd_module_deinit(void) +{ +#if CONFIG_TQ_SCREEN_ENABLE + if (s_lcd.demo_task != NULL) { + vTaskDelete(s_lcd.demo_task); + s_lcd.demo_task = NULL; + } + if (s_lcd.panel != NULL) { + (void)st7789p3_del(s_lcd.panel); + s_lcd.panel = NULL; + } + s_lcd.initialized = false; +#endif +} + +esp_err_t lcd_module_init(void) +{ +#if !CONFIG_TQ_SCREEN_ENABLE + return ESP_ERR_NOT_SUPPORTED; +#else + if (s_lcd.initialized) { + return ESP_OK; + } + + st7789p3_config_t lcd_cfg = ST7789P3_CONFIG_DEFAULT(); + lcd_cfg.spi_host = ST7789_SPI_HOST; + lcd_cfg.pin_miso = CONFIG_TQ_PRINTER_MISO_PIN; + lcd_cfg.pin_mosi = CONFIG_TQ_SPI_SHARED_MOSI_PIN; + lcd_cfg.pin_sclk = CONFIG_TQ_SPI_SHARED_CLK_PIN; + lcd_cfg.pin_cs = CONFIG_TQ_SCREEN_CS_PIN; + lcd_cfg.pin_dc = CONFIG_TQ_SCREEN_DC_PIN; + lcd_cfg.pin_rst = resolve_reset_pin(); + lcd_cfg.pin_bckl = CONFIG_TQ_SCREEN_BACKLIGHT_PIN; + lcd_cfg.backlight_on_level = ST7789_BACKLIGHT_ON_LEVEL; + lcd_cfg.pclk_hz = CONFIG_TQ_SCREEN_PIXEL_CLOCK_HZ; + lcd_cfg.spi_mode = CONFIG_TQ_SCREEN_SPI_MODE; + lcd_cfg.h_res = LCD_DEMO_H_RES; + lcd_cfg.v_res = LCD_DEMO_V_RES; + lcd_cfg.madctl_val = ST7789P3_MADCTL_MX | ST7789P3_MADCTL_MV; + lcd_cfg.invert_color = true; + lcd_cfg.max_transfer_sz = LCD_DEMO_PARALLEL_LINES * LCD_DEMO_H_RES * sizeof(uint16_t) + 8; + + esp_err_t err = st7789p3_new_panel(&lcd_cfg, &s_lcd.panel); + if (err != ESP_OK) { + return err; + } + + err = st7789p3_init(s_lcd.panel); + if (err != ESP_OK) { + lcd_module_deinit(); + return err; + } + + s_lcd.initialized = true; + ESP_LOGI(TAG, + "st7789p3 ready: spi_host=%d mosi=%d clk=%d miso=%d dc=%d cs=%d rst=%d bk=%d pclk=%u", + ST7789_SPI_HOST, + CONFIG_TQ_SPI_SHARED_MOSI_PIN, + CONFIG_TQ_SPI_SHARED_CLK_PIN, + CONFIG_TQ_PRINTER_MISO_PIN, + CONFIG_TQ_SCREEN_DC_PIN, + CONFIG_TQ_SCREEN_CS_PIN, + lcd_cfg.pin_rst, + CONFIG_TQ_SCREEN_BACKLIGHT_PIN, + (unsigned)lcd_cfg.pclk_hz); + return ESP_OK; +#endif +} + +esp_err_t lcd_module_start_demo(void) +{ +#if !CONFIG_TQ_SCREEN_ENABLE + return ESP_ERR_NOT_SUPPORTED; +#else + ESP_RETURN_ON_ERROR(lcd_module_init(), TAG, "display init failed"); + if (s_lcd.demo_task != NULL) { + return ESP_OK; + } + + BaseType_t rc = xTaskCreatePinnedToCore(lcd_demo_task, + "lcd_demo", + LCD_DEMO_TASK_STACK_SIZE, + (void *)s_lcd.panel, + LCD_DEMO_TASK_PRIORITY, + &s_lcd.demo_task, + LCD_DEMO_TASK_CORE_ID); + ESP_RETURN_ON_FALSE(rc == pdPASS, ESP_ERR_NO_MEM, TAG, "lcd demo task create failed"); + return ESP_OK; +#endif +} diff --git a/components/lcd/src/lcd_pretty_effect.c b/components/lcd/src/lcd_pretty_effect.c new file mode 100644 index 0000000..76ee54c --- /dev/null +++ b/components/lcd/src/lcd_pretty_effect.c @@ -0,0 +1,71 @@ +#include "lcd_pretty_effect.h" + +#include +#include + +#include "lcd_decode_image.h" + +static uint16_t *s_pixels; +static int s_prev_frame = -1; +static int8_t s_xofs[PLATFORM_LCD_DEMO_IMAGE_W]; +static int8_t s_yofs[PLATFORM_LCD_DEMO_IMAGE_H]; +static int8_t s_xcomp[PLATFORM_LCD_DEMO_IMAGE_W]; +static int8_t s_ycomp[PLATFORM_LCD_DEMO_IMAGE_H]; + +static inline uint16_t get_bgnd_pixel(int x, int y) +{ + return (uint16_t)*(s_pixels + (y * PLATFORM_LCD_DEMO_IMAGE_W) + x); +} + +esp_err_t platform_lcd_pretty_effect_init(void) +{ + if (s_pixels != NULL) { + return ESP_OK; + } + return platform_lcd_decode_image(&s_pixels); +} + +void platform_lcd_pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect) +{ + if (dest == NULL || linect <= 0) { + return; + } + + if (s_pixels == NULL) { + memset(dest, 0, (size_t)PLATFORM_LCD_DEMO_IMAGE_W * (size_t)linect * sizeof(uint16_t)); + return; + } + + if (frame != s_prev_frame) { + for (int x = 0; x < PLATFORM_LCD_DEMO_IMAGE_W; x++) { + s_xofs[x] = sin(frame * 0.15 + x * 0.06) * 4; + s_xcomp[x] = sin(frame * 0.11 + x * 0.12) * 4; + } + for (int y = 0; y < PLATFORM_LCD_DEMO_IMAGE_H; y++) { + s_yofs[y] = sin(frame * 0.1 + y * 0.05) * 4; + s_ycomp[y] = sin(frame * 0.07 + y * 0.15) * 4; + } + s_prev_frame = frame; + } + + for (int y = line; y < line + linect; y++) { + for (int x = 0; x < PLATFORM_LCD_DEMO_IMAGE_W; x++) { + int sample_x = x + s_yofs[y] + s_xcomp[x]; + int sample_y = y + s_xofs[x] + s_ycomp[y]; + + if (sample_x < 0) { + sample_x = 0; + } else if (sample_x >= PLATFORM_LCD_DEMO_IMAGE_W) { + sample_x = PLATFORM_LCD_DEMO_IMAGE_W - 1; + } + + if (sample_y < 0) { + sample_y = 0; + } else if (sample_y >= PLATFORM_LCD_DEMO_IMAGE_H) { + sample_y = PLATFORM_LCD_DEMO_IMAGE_H - 1; + } + + *dest++ = get_bgnd_pixel(sample_x, sample_y); + } + } +} diff --git a/components/lcd/src/st7789p3.c b/components/lcd/src/st7789p3.c new file mode 100644 index 0000000..582ed21 --- /dev/null +++ b/components/lcd/src/st7789p3.c @@ -0,0 +1,460 @@ +#include "st7789p3.h" + +#include +#include + +#include "driver/gpio.h" +#include "esp_attr.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define ST7789P3_CMD_DELAY_FLAG 0x80 +#define ST7789P3_CMD_DATA_LEN_MASK 0x1F +#define ST7789P3_TX_MAX_CHUNK_BYTES 1024 + +typedef struct { + uint8_t cmd; + uint8_t data[16]; + uint8_t data_bytes; +} st7789p3_lcd_init_cmd_t; + +struct st7789p3_panel_t { + st7789p3_config_t cfg; + spi_device_handle_t spi; + bool bus_owned; +}; + +static const char *TAG = "st7789p3"; + +// Sequence verified on the LCD used by docs/lcd_verification. +DRAM_ATTR static const st7789p3_lcd_init_cmd_t s_st7789p3_init_cmds[] = { + {0x36, {0x00}, 1}, + {0x3A, {0x55}, 1}, + {0xB2, {0x0C, 0x0C, 0x00, 0x33, 0x33}, 5}, + {0xB7, {0x45}, 1}, + {0xBB, {0x2B}, 1}, + {0xC0, {0x2C}, 1}, + {0xC2, {0x01, 0xFF}, 2}, + {0xC3, {0x11}, 1}, + {0xC4, {0x20}, 1}, + {0xC6, {0x0F}, 1}, + {0xD0, {0xA4, 0xA1}, 2}, + {0xE0, {0xD0, 0x00, 0x05, 0x0E, 0x15, 0x0D, 0x37, 0x43, 0x47, 0x09, 0x15, 0x12, 0x16, 0x19}, 14}, + {0xE1, {0xD0, 0x00, 0x05, 0x0D, 0x0C, 0x06, 0x2D, 0x44, 0x40, 0x0E, 0x1C, 0x18, 0x16, 0x19}, 14}, + {0x11, {0}, ST7789P3_CMD_DELAY_FLAG}, + {0, {0}, 0xFF}, +}; + +static esp_err_t st7789p3_validate_config(const st7789p3_config_t *config) +{ + if (config == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (config->pin_mosi < 0 || config->pin_sclk < 0 || config->pin_cs < 0 || config->pin_dc < 0) { + return ESP_ERR_INVALID_ARG; + } + if (config->h_res == 0 || config->v_res == 0) { + return ESP_ERR_INVALID_ARG; + } + if (config->spi_mode > 3) { + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} + +static esp_err_t st7789p3_configure_gpio(st7789p3_handle_t panel) +{ + uint64_t pin_mask = 0; + + pin_mask |= (1ULL << panel->cfg.pin_dc); + if (panel->cfg.pin_rst >= 0) { + pin_mask |= (1ULL << panel->cfg.pin_rst); + } + if (panel->cfg.pin_bckl >= 0) { + pin_mask |= (1ULL << panel->cfg.pin_bckl); + } + + gpio_config_t io_conf = { + .pin_bit_mask = pin_mask, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + + return gpio_config(&io_conf); +} + +static esp_err_t st7789p3_spi_write(st7789p3_handle_t panel, int dc_level, const void *data, size_t data_size) +{ + if (data_size == 0) { + return ESP_OK; + } + + esp_err_t ret = gpio_set_level(panel->cfg.pin_dc, dc_level); + if (ret != ESP_OK) { + return ret; + } + + spi_transaction_t t = {0}; + t.length = data_size * 8; + t.tx_buffer = data; + + return spi_device_transmit(panel->spi, &t); +} + +static esp_err_t st7789p3_send_cmd(st7789p3_handle_t panel, uint8_t cmd) +{ + return st7789p3_spi_write(panel, 0, &cmd, 1); +} + +static esp_err_t st7789p3_send_data(st7789p3_handle_t panel, const void *data, size_t data_size) +{ + const uint8_t *data_ptr = (const uint8_t *)data; + size_t remaining = data_size; + size_t tx_chunk_size = ST7789P3_TX_MAX_CHUNK_BYTES; + + if (panel->cfg.max_transfer_sz > 0 && panel->cfg.max_transfer_sz < tx_chunk_size) { + tx_chunk_size = panel->cfg.max_transfer_sz; + } + + while (remaining > 0) { + size_t chunk = (remaining > tx_chunk_size) ? tx_chunk_size : remaining; + esp_err_t ret = st7789p3_spi_write(panel, 1, data_ptr, chunk); + if (ret != ESP_OK) { + return ret; + } + data_ptr += chunk; + remaining -= chunk; + } + return ESP_OK; +} + +static esp_err_t st7789p3_run_init_cmds(st7789p3_handle_t panel) +{ + for (size_t i = 0; s_st7789p3_init_cmds[i].data_bytes != 0xFF; i++) { + const st7789p3_lcd_init_cmd_t *init_cmd = &s_st7789p3_init_cmds[i]; + uint8_t data_bytes = init_cmd->data_bytes & ST7789P3_CMD_DATA_LEN_MASK; + uint8_t data[16] = {0}; + + if (data_bytes > 0) { + memcpy(data, init_cmd->data, data_bytes); + } + + if (init_cmd->cmd == 0x36 && data_bytes == 1) { + data[0] = panel->cfg.madctl_val; + } + + esp_err_t ret = st7789p3_send_cmd(panel, init_cmd->cmd); + if (ret != ESP_OK) { + return ret; + } + + ret = st7789p3_send_data(panel, data, data_bytes); + if (ret != ESP_OK) { + return ret; + } + + if (init_cmd->data_bytes & ST7789P3_CMD_DELAY_FLAG) { + vTaskDelay(pdMS_TO_TICKS(100)); + } + } + return ESP_OK; +} + +esp_err_t st7789p3_new_panel(const st7789p3_config_t *config, st7789p3_handle_t *ret_panel) +{ + if (ret_panel == NULL) { + return ESP_ERR_INVALID_ARG; + } + *ret_panel = NULL; + + esp_err_t ret = st7789p3_validate_config(config); + if (ret != ESP_OK) { + return ret; + } + + st7789p3_handle_t panel = calloc(1, sizeof(*panel)); + if (panel == NULL) { + return ESP_ERR_NO_MEM; + } + + panel->cfg = *config; + if (panel->cfg.pclk_hz == 0) { + panel->cfg.pclk_hz = 10 * 1000 * 1000; + } + if (panel->cfg.queue_size <= 0) { + panel->cfg.queue_size = 7; + } + if (panel->cfg.max_transfer_sz == 0) { + panel->cfg.max_transfer_sz = panel->cfg.h_res * 20 * sizeof(uint16_t) + 8; + } + + ret = st7789p3_configure_gpio(panel); + if (ret != ESP_OK) { + free(panel); + return ret; + } + + if (panel->cfg.init_spi_bus) { + spi_bus_config_t buscfg = { + .mosi_io_num = panel->cfg.pin_mosi, + .miso_io_num = panel->cfg.pin_miso, + .sclk_io_num = panel->cfg.pin_sclk, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = panel->cfg.max_transfer_sz, + }; + + ret = spi_bus_initialize(panel->cfg.spi_host, &buscfg, SPI_DMA_CH_AUTO); + if (ret == ESP_OK) { + panel->bus_owned = true; + } else if (ret == ESP_ERR_INVALID_STATE) { + ESP_LOGW(TAG, "SPI host already initialized, skip bus init"); + } else { + free(panel); + return ret; + } + } + + spi_device_interface_config_t devcfg = { + .clock_speed_hz = panel->cfg.pclk_hz, + .mode = panel->cfg.spi_mode, + .spics_io_num = panel->cfg.pin_cs, + .queue_size = panel->cfg.queue_size, + }; + + ret = spi_bus_add_device(panel->cfg.spi_host, &devcfg, &panel->spi); + if (ret != ESP_OK) { + if (panel->bus_owned) { + spi_bus_free(panel->cfg.spi_host); + } + free(panel); + return ret; + } + + *ret_panel = panel; + return ESP_OK; +} + +esp_err_t st7789p3_del(st7789p3_handle_t panel) +{ + if (panel == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = ESP_OK; + esp_err_t local_ret = spi_bus_remove_device(panel->spi); + if (local_ret != ESP_OK) { + ret = local_ret; + } + + if (panel->bus_owned) { + local_ret = spi_bus_free(panel->cfg.spi_host); + if (ret == ESP_OK && local_ret != ESP_OK) { + ret = local_ret; + } + } + + free(panel); + return ret; +} + +esp_err_t st7789p3_set_backlight(st7789p3_handle_t panel, bool on) +{ + if (panel == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (panel->cfg.pin_bckl < 0) { + return ESP_OK; + } + + int on_level = panel->cfg.backlight_on_level ? 1 : 0; + int off_level = on_level ? 0 : 1; + return gpio_set_level(panel->cfg.pin_bckl, on ? on_level : off_level); +} + +esp_err_t st7789p3_set_madctl(st7789p3_handle_t panel, uint8_t madctl_val) +{ + if (panel == NULL) { + return ESP_ERR_INVALID_ARG; + } + + panel->cfg.madctl_val = madctl_val; + esp_err_t ret = st7789p3_send_cmd(panel, 0x36); + if (ret != ESP_OK) { + return ret; + } + return st7789p3_send_data(panel, &madctl_val, 1); +} + +esp_err_t st7789p3_set_invert(st7789p3_handle_t panel, bool invert_color) +{ + if (panel == NULL) { + return ESP_ERR_INVALID_ARG; + } + + panel->cfg.invert_color = invert_color; + return st7789p3_send_cmd(panel, invert_color ? 0x21 : 0x20); +} + +esp_err_t st7789p3_reset(st7789p3_handle_t panel) +{ + if (panel == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (panel->cfg.pin_rst < 0) { + return ESP_OK; + } + + esp_err_t ret = gpio_set_level(panel->cfg.pin_rst, 0); + if (ret != ESP_OK) { + return ret; + } + vTaskDelay(pdMS_TO_TICKS(100)); + + ret = gpio_set_level(panel->cfg.pin_rst, 1); + if (ret != ESP_OK) { + return ret; + } + vTaskDelay(pdMS_TO_TICKS(100)); + return ESP_OK; +} + +esp_err_t st7789p3_init(st7789p3_handle_t panel) +{ + if (panel == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = st7789p3_set_backlight(panel, false); + if (ret != ESP_OK) { + return ret; + } + + ret = st7789p3_reset(panel); + if (ret != ESP_OK) { + return ret; + } + + ret = st7789p3_run_init_cmds(panel); + if (ret != ESP_OK) { + return ret; + } + + ret = st7789p3_set_invert(panel, panel->cfg.invert_color); + if (ret != ESP_OK) { + return ret; + } + + ret = st7789p3_send_cmd(panel, 0x29); + if (ret != ESP_OK) { + return ret; + } + vTaskDelay(pdMS_TO_TICKS(100)); + + return st7789p3_set_backlight(panel, true); +} + +esp_err_t st7789p3_set_window( + st7789p3_handle_t panel, uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end) +{ + if (panel == NULL || x_start >= x_end || y_start >= y_end) { + return ESP_ERR_INVALID_ARG; + } + if (x_end > panel->cfg.h_res || y_end > panel->cfg.v_res) { + return ESP_ERR_INVALID_ARG; + } + + uint8_t x_data[4] = { + (uint8_t)(x_start >> 8), + (uint8_t)(x_start & 0xFF), + (uint8_t)((x_end - 1) >> 8), + (uint8_t)((x_end - 1) & 0xFF), + }; + uint8_t y_data[4] = { + (uint8_t)(y_start >> 8), + (uint8_t)(y_start & 0xFF), + (uint8_t)((y_end - 1) >> 8), + (uint8_t)((y_end - 1) & 0xFF), + }; + + esp_err_t ret = st7789p3_send_cmd(panel, 0x2A); + if (ret != ESP_OK) { + return ret; + } + ret = st7789p3_send_data(panel, x_data, sizeof(x_data)); + if (ret != ESP_OK) { + return ret; + } + + ret = st7789p3_send_cmd(panel, 0x2B); + if (ret != ESP_OK) { + return ret; + } + ret = st7789p3_send_data(panel, y_data, sizeof(y_data)); + if (ret != ESP_OK) { + return ret; + } + + return st7789p3_send_cmd(panel, 0x2C); +} + +esp_err_t st7789p3_draw_bitmap(st7789p3_handle_t panel, + uint16_t x_start, + uint16_t y_start, + uint16_t x_end, + uint16_t y_end, + const uint16_t *color_data) +{ + if (panel == NULL || color_data == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = st7789p3_set_window(panel, x_start, y_start, x_end, y_end); + if (ret != ESP_OK) { + return ret; + } + + size_t pixel_count = (size_t)(x_end - x_start) * (size_t)(y_end - y_start); + return st7789p3_send_data(panel, color_data, pixel_count * sizeof(uint16_t)); +} + +esp_err_t st7789p3_fill_color(st7789p3_handle_t panel, uint16_t color) +{ + if (panel == NULL) { + return ESP_ERR_INVALID_ARG; + } + + static const size_t fill_pixels = 256; + uint16_t *fill_buffer = heap_caps_malloc(fill_pixels * sizeof(uint16_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + if (fill_buffer == NULL) { + return ESP_ERR_NO_MEM; + } + + for (size_t i = 0; i < fill_pixels; i++) { + fill_buffer[i] = color; + } + + esp_err_t ret = st7789p3_set_window(panel, 0, 0, panel->cfg.h_res, panel->cfg.v_res); + if (ret != ESP_OK) { + free(fill_buffer); + return ret; + } + + size_t total_pixels = (size_t)panel->cfg.h_res * (size_t)panel->cfg.v_res; + while (total_pixels > 0) { + size_t pixels_to_send = (total_pixels > fill_pixels) ? fill_pixels : total_pixels; + ret = st7789p3_send_data(panel, fill_buffer, pixels_to_send * sizeof(uint16_t)); + if (ret != ESP_OK) { + free(fill_buffer); + return ret; + } + total_pixels -= pixels_to_send; + } + + free(fill_buffer); + return ESP_OK; +} diff --git a/components/platform/CMakeLists.txt b/components/platform/CMakeLists.txt index 1efdb67..0d35768 100644 --- a/components/platform/CMakeLists.txt +++ b/components/platform/CMakeLists.txt @@ -13,6 +13,7 @@ idf_component_register( PRIV_INCLUDE_DIRS "internal" REQUIRES + lcd bt esp_coex esp_wifi @@ -21,7 +22,6 @@ idf_component_register( nvs_flash mbedtls esp_adc - esp_lcd esp_codec_dev esp_audio_codec driver diff --git a/components/platform/src/display_st7789.c b/components/platform/src/display_st7789.c index 6bf2f46..2b5ddea 100644 --- a/components/platform/src/display_st7789.c +++ b/components/platform/src/display_st7789.c @@ -1,317 +1,18 @@ #include "platform.h" -#include -#include -#include +#include "lcd.h" -#include "driver/gpio.h" -#include "driver/spi_master.h" -#include "esp_check.h" -#include "esp_heap_caps.h" -#include "esp_lcd_panel_io.h" -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_panel_vendor.h" -#include "esp_log.h" -#include "sdkconfig.h" - -static const char *TAG = "display_st7789"; - -#define ST7789_SPI_HOST SPI2_HOST -#define ST7789_COLOR_BYTES_PER_PIXEL 2 - -#ifndef CONFIG_TQ_SCREEN_SPI_MODE -#define CONFIG_TQ_SCREEN_SPI_MODE 0 -#endif - -#ifndef CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH -#define CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH 1 -#endif - -#if CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH -#define ST7789_BACKLIGHT_ON_LEVEL 1 -#define ST7789_BACKLIGHT_OFF_LEVEL 0 -#else -#define ST7789_BACKLIGHT_ON_LEVEL 0 -#define ST7789_BACKLIGHT_OFF_LEVEL 1 -#endif - -typedef struct { - esp_lcd_panel_io_handle_t io_handle; - esp_lcd_panel_handle_t panel_handle; - bool bus_owned; - bool initialized; -} st7789_display_state_t; - -static st7789_display_state_t s_display; - -#if CONFIG_TQ_SCREEN_COLOR_ORDER_BGR -#define ST7789_COLOR_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#else -#define ST7789_COLOR_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#endif - -#if CONFIG_TQ_SCREEN_SWAP_XY -#define ST7789_SWAP_XY true -#else -#define ST7789_SWAP_XY false -#endif - -#if CONFIG_TQ_SCREEN_MIRROR_X -#define ST7789_MIRROR_X true -#else -#define ST7789_MIRROR_X false -#endif - -#if CONFIG_TQ_SCREEN_MIRROR_Y -#define ST7789_MIRROR_Y true -#else -#define ST7789_MIRROR_Y false -#endif - -static uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b) { - return (uint16_t)(((uint16_t)(r & 0xF8) << 8) | - ((uint16_t)(g & 0xFC) << 3) | - ((uint16_t)(b & 0xF8) >> 3)); +void platform_display_deinit(void) +{ + lcd_module_deinit(); } -static uint16_t test_pattern_color(int x, int y, int h_res, int v_res) { - int top = v_res / 3; - int middle = (v_res * 2) / 3; - - if (y < top) { - uint8_t r = (uint8_t)((x * 255) / (h_res - 1)); - uint8_t g = (uint8_t)(255 - r); - return rgb565(r, g, 48); - } - - if (y < middle) { - uint8_t gray = (uint8_t)(((y - top) * 255) / ((middle - top) > 1 ? (middle - top - 1) : 1)); - return rgb565(gray, gray, gray); - } - - bool checker = (((x / 16) + (y / 16)) & 1) != 0; - return checker ? rgb565(250, 250, 250) : rgb565(8, 8, 8); +esp_err_t platform_display_init(void) +{ + return lcd_module_init(); } -static void fill_test_pattern_chunk(uint16_t *buf, - int y_start, - int lines, - int h_res, - int v_res) { - for (int row = 0; row < lines; ++row) { - int y = y_start + row; - for (int x = 0; x < h_res; ++x) { - uint16_t color = test_pattern_color(x, y, h_res, v_res); - - if (x == 0 || y == 0 || x == (h_res - 1) || y == (v_res - 1)) { - color = rgb565(255, 0, 0); - } else if (x == (h_res / 2) || y == (v_res / 2)) { - color = rgb565(255, 255, 255); - } - - buf[row * h_res + x] = color; - } - } -} - -void platform_display_deinit(void) { -#if CONFIG_TQ_SCREEN_ENABLE - if (CONFIG_TQ_SCREEN_BACKLIGHT_PIN >= 0) { - (void)gpio_set_level(CONFIG_TQ_SCREEN_BACKLIGHT_PIN, ST7789_BACKLIGHT_OFF_LEVEL); - } - - if (s_display.panel_handle != NULL) { - (void)esp_lcd_panel_del(s_display.panel_handle); - s_display.panel_handle = NULL; - } - if (s_display.io_handle != NULL) { - (void)esp_lcd_panel_io_del(s_display.io_handle); - s_display.io_handle = NULL; - } - if (s_display.bus_owned) { - (void)spi_bus_free(ST7789_SPI_HOST); - s_display.bus_owned = false; - } - s_display.initialized = false; -#endif -} - -esp_err_t platform_display_init(void) { -#if !CONFIG_TQ_SCREEN_ENABLE - return ESP_ERR_NOT_SUPPORTED; -#else - if (s_display.initialized) { - return ESP_OK; - } - - if (CONFIG_TQ_SCREEN_BACKLIGHT_PIN >= 0) { - ESP_RETURN_ON_ERROR(gpio_set_level(CONFIG_TQ_SCREEN_BACKLIGHT_PIN, ST7789_BACKLIGHT_OFF_LEVEL), - TAG, - "set backlight off failed"); - } - - const size_t max_transfer_size = (size_t)CONFIG_TQ_SCREEN_H_RES * - (size_t)CONFIG_TQ_SCREEN_DRAW_LINES * - ST7789_COLOR_BYTES_PER_PIXEL + 8; - - spi_bus_config_t bus_cfg = { - .sclk_io_num = CONFIG_TQ_SPI_SHARED_CLK_PIN, - .mosi_io_num = CONFIG_TQ_SPI_SHARED_MOSI_PIN, - .miso_io_num = -1, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = (int)max_transfer_size, - }; - - esp_err_t err = spi_bus_initialize(ST7789_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO); - if (err == ESP_OK) { - s_display.bus_owned = true; - } else if (err == ESP_ERR_INVALID_STATE) { - s_display.bus_owned = false; - ESP_LOGW(TAG, "SPI host already initialized, reuse host=%d", ST7789_SPI_HOST); - } else { - return err; - } - - esp_lcd_panel_io_spi_config_t io_cfg = { - .cs_gpio_num = CONFIG_TQ_SCREEN_CS_PIN, - .dc_gpio_num = CONFIG_TQ_SCREEN_DC_PIN, - .spi_mode = CONFIG_TQ_SCREEN_SPI_MODE, - .pclk_hz = CONFIG_TQ_SCREEN_PIXEL_CLOCK_HZ, - .trans_queue_depth = 1, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - }; - err = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)ST7789_SPI_HOST, &io_cfg, &s_display.io_handle); - if (err != ESP_OK) { - platform_display_deinit(); - return err; - } - - esp_lcd_panel_dev_config_t panel_cfg = { - .reset_gpio_num = CONFIG_TQ_SCREEN_RESET_PIN, - .rgb_ele_order = ST7789_COLOR_ORDER, - .bits_per_pixel = 16, - }; - err = esp_lcd_new_panel_st7789(s_display.io_handle, &panel_cfg, &s_display.panel_handle); - if (err != ESP_OK) { - platform_display_deinit(); - return err; - } - - err = esp_lcd_panel_reset(s_display.panel_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "panel reset failed: %s", esp_err_to_name(err)); - platform_display_deinit(); - return err; - } - err = esp_lcd_panel_init(s_display.panel_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "panel init failed: %s", esp_err_to_name(err)); - platform_display_deinit(); - return err; - } - err = esp_lcd_panel_swap_xy(s_display.panel_handle, ST7789_SWAP_XY); - if (err != ESP_OK) { - ESP_LOGE(TAG, "swap xy failed: %s", esp_err_to_name(err)); - platform_display_deinit(); - return err; - } - err = esp_lcd_panel_mirror(s_display.panel_handle, ST7789_MIRROR_X, ST7789_MIRROR_Y); - if (err != ESP_OK) { - ESP_LOGE(TAG, "mirror failed: %s", esp_err_to_name(err)); - platform_display_deinit(); - return err; - } - err = esp_lcd_panel_set_gap(s_display.panel_handle, CONFIG_TQ_SCREEN_X_GAP, CONFIG_TQ_SCREEN_Y_GAP); - if (err != ESP_OK) { - ESP_LOGE(TAG, "set gap failed: %s", esp_err_to_name(err)); - platform_display_deinit(); - return err; - } - err = esp_lcd_panel_invert_color(s_display.panel_handle, false); - if (err != ESP_OK) { - ESP_LOGE(TAG, "invert control failed: %s", esp_err_to_name(err)); - platform_display_deinit(); - return err; - } - err = esp_lcd_panel_disp_on_off(s_display.panel_handle, true); - if (err != ESP_OK) { - ESP_LOGE(TAG, "display on failed: %s", esp_err_to_name(err)); - platform_display_deinit(); - return err; - } - - if (CONFIG_TQ_SCREEN_BACKLIGHT_PIN >= 0) { - err = gpio_set_level(CONFIG_TQ_SCREEN_BACKLIGHT_PIN, ST7789_BACKLIGHT_ON_LEVEL); - if (err != ESP_OK) { - ESP_LOGE(TAG, "set backlight on failed: %s", esp_err_to_name(err)); - platform_display_deinit(); - return err; - } - } - - s_display.initialized = true; - ESP_LOGI(TAG, - "st7789 ready: spi_host=%d sclk=%d mosi=%d dc=%d cs=%d rst=%d bk=%d bk_on=%d spi_mode=%d size=%dx%d pclk=%u", - ST7789_SPI_HOST, - CONFIG_TQ_SPI_SHARED_CLK_PIN, - CONFIG_TQ_SPI_SHARED_MOSI_PIN, - CONFIG_TQ_SCREEN_DC_PIN, - CONFIG_TQ_SCREEN_CS_PIN, - CONFIG_TQ_SCREEN_RESET_PIN, - CONFIG_TQ_SCREEN_BACKLIGHT_PIN, - ST7789_BACKLIGHT_ON_LEVEL, - CONFIG_TQ_SCREEN_SPI_MODE, - CONFIG_TQ_SCREEN_H_RES, - CONFIG_TQ_SCREEN_V_RES, - (unsigned)CONFIG_TQ_SCREEN_PIXEL_CLOCK_HZ); - return ESP_OK; -#endif -} - -esp_err_t platform_display_show_test_pattern(void) { -#if !CONFIG_TQ_SCREEN_ENABLE - return ESP_ERR_NOT_SUPPORTED; -#else - ESP_RETURN_ON_ERROR(platform_display_init(), TAG, "display init failed"); - - const int h_res = CONFIG_TQ_SCREEN_H_RES; - const int v_res = CONFIG_TQ_SCREEN_V_RES; - const int draw_lines = CONFIG_TQ_SCREEN_DRAW_LINES > 0 ? CONFIG_TQ_SCREEN_DRAW_LINES : 1; - const size_t buf_pixels = (size_t)h_res * (size_t)draw_lines; - const size_t buf_size = buf_pixels * ST7789_COLOR_BYTES_PER_PIXEL; - - uint16_t *draw_buf = (uint16_t *)heap_caps_malloc(buf_size, MALLOC_CAP_DMA | MALLOC_CAP_8BIT); - if (draw_buf == NULL) { - draw_buf = (uint16_t *)heap_caps_malloc(buf_size, MALLOC_CAP_8BIT); - } - ESP_RETURN_ON_FALSE(draw_buf != NULL, ESP_ERR_NO_MEM, TAG, "alloc draw buffer failed"); - - ESP_LOGI(TAG, "draw test pattern start"); - - esp_err_t err = ESP_OK; - for (int y = 0; y < v_res && err == ESP_OK; y += draw_lines) { - int chunk_lines = draw_lines; - if (y + chunk_lines > v_res) { - chunk_lines = v_res - y; - } - - fill_test_pattern_chunk(draw_buf, y, chunk_lines, h_res, v_res); - err = esp_lcd_panel_draw_bitmap(s_display.panel_handle, 0, y, h_res, y + chunk_lines, draw_buf); - if (err != ESP_OK) { - break; - } - - // Wait for queued color transfer to finish before reusing draw_buf. - err = esp_lcd_panel_io_tx_param(s_display.io_handle, -1, NULL, 0); - } - - heap_caps_free(draw_buf); - - if (err == ESP_OK) { - ESP_LOGI(TAG, "draw test pattern done"); - } - return err; -#endif +esp_err_t platform_display_show_test_pattern(void) +{ + return lcd_module_start_demo(); } diff --git a/dependencies.lock b/dependencies.lock index 6037eb8..95fa7a2 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -19,6 +19,16 @@ dependencies: registry_url: https://components.espressif.com/ type: service version: 1.5.4 + espressif/esp_jpeg: + component_hash: defb83669293cbf86d0fa86b475ba5517aceed04ed70db435388c151ab37b5d7 + dependencies: + - name: idf + require: private + version: '>=5.0' + source: + registry_url: https://components.espressif.com/ + type: service + version: 1.3.1 espressif/esp_websocket_client: component_hash: c5a067a9fddea370c478017e66fac302f4b79c3d4027e9bdd42a019786cceb92 dependencies: @@ -56,13 +66,14 @@ dependencies: idf: source: type: idf - version: 5.5.2 + version: 5.5.1 direct_dependencies: - espressif/esp_audio_codec - espressif/esp_codec_dev +- espressif/esp_jpeg - espressif/esp_websocket_client - espressif/libpng - idf -manifest_hash: 3274b53ce89a58abbad0a03dfaff3410e35deb81305a21289606c4d2177a111b +manifest_hash: 5900d46fda5cdfbcdd8ddd277f3cf83d1ca7f79f4a98eb428297e57174c5181c target: esp32s3 version: 2.0.0 diff --git a/dependency_whitelist.md b/dependency_whitelist.md index a77af50..727d338 100644 --- a/dependency_whitelist.md +++ b/dependency_whitelist.md @@ -10,4 +10,4 @@ Entry format: - expiry: YYYY-MM-DD (must be reviewed before expiry) Current entries: -- none +- requester: `platform/platform`; target: `platform/lcd`; reason: split LCD driver/demo into dedicated component under `components/lcd`; owner: ai-agent; expiry: 2026-12-31 diff --git a/main/idf_component.yml b/main/idf_component.yml index eb66955..663bfd6 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -17,4 +17,5 @@ dependencies: espressif/esp_websocket_client: ^1.6.1 espressif/esp_codec_dev: ^1.5.4 espressif/esp_audio_codec: ^2.4.1 + espressif/esp_jpeg: ">=1.0.2" espressif/libpng: ^1.6.55