lvgl驱动成功,且能显示切换图片
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "domain.h"
|
||||
|
||||
static const char *TAG = "rest_print";
|
||||
#define SCREEN_PREVIEW_TIMEOUT_MS 200
|
||||
|
||||
typedef struct {
|
||||
bool scale_to_width;
|
||||
@@ -355,6 +356,42 @@ static esp_err_t rest_server_send_image_generation_error(httpd_req_t *req,
|
||||
return rest_server_send_error(req, "502 Bad Gateway", message);
|
||||
}
|
||||
|
||||
static void rest_server_try_preview_raster(const char *source,
|
||||
const uint8_t *raster,
|
||||
size_t raster_len,
|
||||
uint16_t width,
|
||||
uint16_t height) {
|
||||
if (raster == NULL || raster_len == 0 || width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char preview_err[96] = {0};
|
||||
esp_err_t preview_rc = screen_preview_show_raster(raster,
|
||||
raster_len,
|
||||
width,
|
||||
height,
|
||||
SCREEN_PREVIEW_TIMEOUT_MS,
|
||||
preview_err,
|
||||
sizeof(preview_err));
|
||||
if (preview_rc == ESP_OK) {
|
||||
ESP_LOGI(TAG,
|
||||
"screen preview updated (%s), size=%ux%u",
|
||||
source != NULL ? source : "unknown",
|
||||
(unsigned)width,
|
||||
(unsigned)height);
|
||||
return;
|
||||
}
|
||||
if (preview_rc == ESP_ERR_NOT_SUPPORTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG,
|
||||
"screen preview skipped (%s), rc=0x%x, msg=%s",
|
||||
source != NULL ? source : "unknown",
|
||||
(unsigned)preview_rc,
|
||||
preview_err[0] != '\0' ? preview_err : "preview failed");
|
||||
}
|
||||
|
||||
static esp_err_t rest_server_print_image_binary(httpd_req_t *req) {
|
||||
bool scale_to_width = true;
|
||||
uint8_t threshold = 160;
|
||||
@@ -419,6 +456,7 @@ static esp_err_t rest_server_print_image_binary(httpd_req_t *req) {
|
||||
(unsigned)width,
|
||||
(unsigned)height,
|
||||
(unsigned)raster_len);
|
||||
rest_server_try_preview_raster("upload", raster, raster_len, width, height);
|
||||
|
||||
esp_err_t submit_rc = rest_server_print_submit_raster_job_and_reply(req,
|
||||
raster,
|
||||
@@ -562,6 +600,7 @@ static esp_err_t rest_server_print_image_generate(httpd_req_t *req) {
|
||||
(unsigned)width,
|
||||
(unsigned)height,
|
||||
(unsigned)raster_len);
|
||||
rest_server_try_preview_raster("generated", raster, raster_len, width, height);
|
||||
|
||||
char warning[160] = {0};
|
||||
if (request_id[0] != '\0') {
|
||||
|
||||
@@ -7,6 +7,7 @@ idf_component_register(
|
||||
"src/raster_tools.c"
|
||||
"src/raster_tools_image_qr.c"
|
||||
"src/image_generation.c"
|
||||
"src/screen_preview.c"
|
||||
"src/system_runtime.c"
|
||||
"src/voice_interaction.c"
|
||||
"src/voice_interaction_common.c"
|
||||
|
||||
@@ -100,6 +100,15 @@ esp_err_t image_generation_generate_png(const image_generation_request_t *req,
|
||||
char *err,
|
||||
size_t err_len);
|
||||
|
||||
// ---------- screen_preview ----------
|
||||
esp_err_t screen_preview_show_raster(const uint8_t *raster,
|
||||
size_t raster_len,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
uint32_t timeout_ms,
|
||||
char *err,
|
||||
size_t err_len);
|
||||
|
||||
// ---------- printer_protocol ----------
|
||||
typedef enum {
|
||||
PRINT_JOB_STATE_NONE = 0,
|
||||
|
||||
12
components/domain/src/screen_preview.c
Normal file
12
components/domain/src/screen_preview.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "domain.h"
|
||||
|
||||
esp_err_t screen_preview_show_raster(const uint8_t *raster,
|
||||
size_t raster_len,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
uint32_t timeout_ms,
|
||||
char *err,
|
||||
size_t err_len)
|
||||
{
|
||||
return platform_display_show_raster_1bpp(raster, raster_len, width, height, timeout_ms, err, err_len);
|
||||
}
|
||||
@@ -12,6 +12,7 @@ idf_component_register(
|
||||
driver
|
||||
esp_driver_gpio
|
||||
esp_driver_spi
|
||||
lvgl
|
||||
espressif__esp_jpeg
|
||||
EMBED_FILES
|
||||
"assets/lcd_demo.jpg"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -8,6 +11,13 @@ extern "C" {
|
||||
|
||||
esp_err_t lcd_module_init(void);
|
||||
esp_err_t lcd_module_start_demo(void);
|
||||
esp_err_t lcd_module_show_raster_1bpp(const uint8_t *raster,
|
||||
size_t raster_len,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
uint32_t timeout_ms,
|
||||
char *err,
|
||||
size_t err_len);
|
||||
void lcd_module_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,30 +1,37 @@
|
||||
#include "lcd.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 "freertos/semphr.h"
|
||||
#include "lvgl.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "st7789p3.h"
|
||||
|
||||
static const char *TAG = "lcd_demo";
|
||||
static const char *TAG = "lcd_module";
|
||||
|
||||
#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
|
||||
#define LCD_PANEL_H_RES 320
|
||||
#define LCD_PANEL_V_RES 240
|
||||
#define LCD_PREVIEW_TIMEOUT_MS_DEFAULT 200
|
||||
#define LCD_LOCK_TIMEOUT_MS 1000
|
||||
#define LCD_DRAW_LINES 20
|
||||
|
||||
#ifndef CONFIG_TQ_SCREEN_SPI_MODE
|
||||
#define CONFIG_TQ_SCREEN_SPI_MODE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TQ_SCREEN_DRAW_LINES
|
||||
#define CONFIG_TQ_SCREEN_DRAW_LINES LCD_DRAW_LINES
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH
|
||||
#define CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH 1
|
||||
#endif
|
||||
@@ -37,7 +44,18 @@ static const char *TAG = "lcd_demo";
|
||||
|
||||
typedef struct {
|
||||
st7789p3_handle_t panel;
|
||||
TaskHandle_t demo_task;
|
||||
SemaphoreHandle_t lock;
|
||||
lv_disp_draw_buf_t lv_draw_buf;
|
||||
lv_disp_drv_t lv_drv;
|
||||
lv_disp_t *lv_disp;
|
||||
lv_obj_t *preview_img;
|
||||
lv_obj_t *demo_label;
|
||||
lv_color_t *draw_buf_1;
|
||||
lv_color_t *draw_buf_2;
|
||||
uint16_t *preview_pixels;
|
||||
lv_img_dsc_t preview_dsc;
|
||||
bool lvgl_inited;
|
||||
bool lvgl_ready;
|
||||
bool initialized;
|
||||
} lcd_state_t;
|
||||
|
||||
@@ -51,70 +69,238 @@ static int resolve_reset_pin(void)
|
||||
return CONFIG_TQ_SCREEN_BACKLIGHT_PIN;
|
||||
}
|
||||
|
||||
static void lcd_demo_task(void *arg)
|
||||
static void lcd_fill_err(char *err, size_t err_len, const char *msg)
|
||||
{
|
||||
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;
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "%s", msg != NULL ? msg : "unknown");
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t err = platform_lcd_pretty_effect_init();
|
||||
static bool lcd_lock_take(uint32_t timeout_ms)
|
||||
{
|
||||
if (s_lcd.lock == NULL) {
|
||||
return false;
|
||||
}
|
||||
TickType_t ticks = pdMS_TO_TICKS(timeout_ms);
|
||||
if (timeout_ms > 0 && ticks == 0) {
|
||||
ticks = 1;
|
||||
}
|
||||
return xSemaphoreTake(s_lcd.lock, ticks) == pdTRUE;
|
||||
}
|
||||
|
||||
static void lcd_lock_give(void)
|
||||
{
|
||||
if (s_lcd.lock != NULL) {
|
||||
xSemaphoreGive(s_lcd.lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void *lcd_alloc_fb(size_t bytes)
|
||||
{
|
||||
void *buf = heap_caps_malloc(bytes, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
if (buf == NULL) {
|
||||
buf = heap_caps_malloc(bytes, MALLOC_CAP_8BIT);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void lcd_free_lvgl_buffers(void)
|
||||
{
|
||||
if (s_lcd.draw_buf_1 != NULL) {
|
||||
heap_caps_free(s_lcd.draw_buf_1);
|
||||
s_lcd.draw_buf_1 = NULL;
|
||||
}
|
||||
if (s_lcd.draw_buf_2 != NULL) {
|
||||
heap_caps_free(s_lcd.draw_buf_2);
|
||||
s_lcd.draw_buf_2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_lvgl_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
{
|
||||
st7789p3_handle_t panel = (st7789p3_handle_t)disp_drv->user_data;
|
||||
if (panel == NULL || area == NULL || color_map == NULL) {
|
||||
lv_disp_flush_ready(disp_drv);
|
||||
return;
|
||||
}
|
||||
if (area->x1 < 0 || area->y1 < 0 || area->x2 < area->x1 || area->y2 < area->y1) {
|
||||
lv_disp_flush_ready(disp_drv);
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t err = st7789p3_draw_bitmap(panel,
|
||||
(uint16_t)area->x1,
|
||||
(uint16_t)area->y1,
|
||||
(uint16_t)(area->x2 + 1),
|
||||
(uint16_t)(area->y2 + 1),
|
||||
(const uint16_t *)color_map);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "pretty effect init failed: %s", esp_err_to_name(err));
|
||||
goto exit;
|
||||
ESP_LOGW(TAG, "lvgl flush failed: %s", esp_err_to_name(err));
|
||||
}
|
||||
lv_disp_flush_ready(disp_drv);
|
||||
}
|
||||
|
||||
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);
|
||||
static esp_err_t lcd_lvgl_init_locked(void)
|
||||
{
|
||||
if (s_lcd.lvgl_ready) {
|
||||
return ESP_OK;
|
||||
}
|
||||
if (lines[i] == NULL) {
|
||||
ESP_LOGE(TAG, "lcd demo line buffer alloc failed");
|
||||
goto exit;
|
||||
|
||||
if (!s_lcd.lvgl_inited) {
|
||||
lv_init();
|
||||
s_lcd.lvgl_inited = true;
|
||||
}
|
||||
|
||||
const size_t draw_buf_pixels = LCD_PANEL_H_RES * CONFIG_TQ_SCREEN_DRAW_LINES;
|
||||
const size_t draw_buf_bytes = draw_buf_pixels * sizeof(lv_color_t);
|
||||
s_lcd.draw_buf_1 = (lv_color_t *)lcd_alloc_fb(draw_buf_bytes);
|
||||
if (s_lcd.draw_buf_1 == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
s_lcd.draw_buf_2 = (lv_color_t *)lcd_alloc_fb(draw_buf_bytes);
|
||||
if (s_lcd.draw_buf_2 == NULL) {
|
||||
lcd_free_lvgl_buffers();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
lv_disp_draw_buf_init(&s_lcd.lv_draw_buf, s_lcd.draw_buf_1, s_lcd.draw_buf_2, draw_buf_pixels);
|
||||
|
||||
lv_disp_drv_init(&s_lcd.lv_drv);
|
||||
s_lcd.lv_drv.hor_res = LCD_PANEL_H_RES;
|
||||
s_lcd.lv_drv.ver_res = LCD_PANEL_V_RES;
|
||||
s_lcd.lv_drv.flush_cb = lcd_lvgl_flush_cb;
|
||||
s_lcd.lv_drv.draw_buf = &s_lcd.lv_draw_buf;
|
||||
s_lcd.lv_drv.user_data = s_lcd.panel;
|
||||
s_lcd.lv_disp = lv_disp_drv_register(&s_lcd.lv_drv);
|
||||
if (s_lcd.lv_disp == NULL) {
|
||||
lcd_free_lvgl_buffers();
|
||||
ESP_LOGE(TAG, "lvgl display register failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_set_style_bg_color(screen, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_clear_flag(screen, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
s_lcd.preview_img = lv_img_create(screen);
|
||||
lv_obj_add_flag(s_lcd.preview_img, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_center(s_lcd.preview_img);
|
||||
|
||||
s_lcd.lvgl_ready = true;
|
||||
lv_refr_now(s_lcd.lv_disp);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void lcd_calc_preview_size(uint16_t src_w, uint16_t src_h, uint16_t *out_w, uint16_t *out_h)
|
||||
{
|
||||
if (src_w == 0 || src_h == 0 || out_w == NULL || out_h == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (src_w <= LCD_PANEL_H_RES && src_h <= LCD_PANEL_V_RES) {
|
||||
*out_w = src_w;
|
||||
*out_h = src_h;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((uint64_t)src_w * LCD_PANEL_V_RES > (uint64_t)src_h * LCD_PANEL_H_RES) {
|
||||
*out_w = LCD_PANEL_H_RES;
|
||||
*out_h = (uint16_t)(((uint32_t)src_h * LCD_PANEL_H_RES) / src_w);
|
||||
} else {
|
||||
*out_h = LCD_PANEL_V_RES;
|
||||
*out_w = (uint16_t)(((uint32_t)src_w * LCD_PANEL_V_RES) / src_h);
|
||||
}
|
||||
if (*out_w == 0) {
|
||||
*out_w = 1;
|
||||
}
|
||||
if (*out_h == 0) {
|
||||
*out_h = 1;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
static esp_err_t lcd_render_raster_to_rgb565(const uint8_t *raster,
|
||||
size_t raster_len,
|
||||
uint16_t src_w,
|
||||
uint16_t src_h,
|
||||
uint16_t **out_pixels,
|
||||
uint16_t *out_w,
|
||||
uint16_t *out_h,
|
||||
char *err,
|
||||
size_t err_len)
|
||||
{
|
||||
if (raster == NULL || src_w == 0 || src_h == 0 || out_pixels == NULL || out_w == NULL || out_h == NULL) {
|
||||
lcd_fill_err(err, err_len, "invalid raster");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
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;
|
||||
size_t bytes_per_row = ((size_t)src_w + 7u) / 8u;
|
||||
size_t needed_len = bytes_per_row * src_h;
|
||||
if (raster_len < needed_len) {
|
||||
lcd_fill_err(err, err_len, "raster length mismatch");
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
draw_buffer_index ^= 1;
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
lcd_calc_preview_size(src_w, src_h, out_w, out_h);
|
||||
size_t pixel_count = (size_t)(*out_w) * (size_t)(*out_h);
|
||||
if (pixel_count == 0 || pixel_count > SIZE_MAX / sizeof(uint16_t)) {
|
||||
lcd_fill_err(err, err_len, "preview size invalid");
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
uint16_t *pixels = (uint16_t *)heap_caps_malloc(pixel_count * sizeof(uint16_t),
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if (pixels == NULL) {
|
||||
pixels = (uint16_t *)heap_caps_malloc(pixel_count * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
||||
}
|
||||
if (pixels == NULL) {
|
||||
lcd_fill_err(err, err_len, "no memory");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
for (uint16_t y = 0; y < *out_h; ++y) {
|
||||
uint16_t src_y = (uint16_t)(((uint32_t)y * src_h) / (*out_h));
|
||||
size_t row_base = (size_t)src_y * bytes_per_row;
|
||||
size_t out_row = (size_t)y * (*out_w);
|
||||
for (uint16_t x = 0; x < *out_w; ++x) {
|
||||
uint16_t src_x = (uint16_t)(((uint32_t)x * src_w) / (*out_w));
|
||||
size_t byte_idx = row_base + (src_x / 8u);
|
||||
uint8_t bit = (uint8_t)(7u - (src_x % 8u));
|
||||
bool is_black = (raster[byte_idx] & (uint8_t)(1u << bit)) != 0;
|
||||
pixels[out_row + x] = is_black ? 0x0000 : 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
*out_pixels = pixels;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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.lock != NULL) {
|
||||
(void)xSemaphoreTake(s_lcd.lock, portMAX_DELAY);
|
||||
}
|
||||
|
||||
if (s_lcd.lv_disp != NULL) {
|
||||
lv_disp_remove(s_lcd.lv_disp);
|
||||
s_lcd.lv_disp = NULL;
|
||||
}
|
||||
if (s_lcd.preview_pixels != NULL) {
|
||||
heap_caps_free(s_lcd.preview_pixels);
|
||||
s_lcd.preview_pixels = NULL;
|
||||
}
|
||||
lcd_free_lvgl_buffers();
|
||||
s_lcd.preview_img = NULL;
|
||||
s_lcd.demo_label = NULL;
|
||||
s_lcd.lvgl_ready = false;
|
||||
|
||||
if (s_lcd.lock != NULL) {
|
||||
xSemaphoreGive(s_lcd.lock);
|
||||
vSemaphoreDelete(s_lcd.lock);
|
||||
s_lcd.lock = NULL;
|
||||
}
|
||||
|
||||
if (s_lcd.panel != NULL) {
|
||||
(void)st7789p3_del(s_lcd.panel);
|
||||
s_lcd.panel = NULL;
|
||||
@@ -144,11 +330,11 @@ esp_err_t lcd_module_init(void)
|
||||
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.h_res = LCD_PANEL_H_RES;
|
||||
lcd_cfg.v_res = LCD_PANEL_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;
|
||||
lcd_cfg.max_transfer_sz = CONFIG_TQ_SCREEN_DRAW_LINES * LCD_PANEL_H_RES * sizeof(uint16_t) + 8;
|
||||
|
||||
esp_err_t err = st7789p3_new_panel(&lcd_cfg, &s_lcd.panel);
|
||||
if (err != ESP_OK) {
|
||||
@@ -161,6 +347,23 @@ esp_err_t lcd_module_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
s_lcd.lock = xSemaphoreCreateMutex();
|
||||
if (s_lcd.lock == NULL) {
|
||||
lcd_module_deinit();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
if (!lcd_lock_take(LCD_LOCK_TIMEOUT_MS)) {
|
||||
lcd_module_deinit();
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
err = lcd_lvgl_init_locked();
|
||||
lcd_lock_give();
|
||||
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",
|
||||
@@ -177,24 +380,103 @@ esp_err_t lcd_module_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t lcd_module_show_raster_1bpp(const uint8_t *raster,
|
||||
size_t raster_len,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
uint32_t timeout_ms,
|
||||
char *err,
|
||||
size_t err_len)
|
||||
{
|
||||
#if !CONFIG_TQ_SCREEN_ENABLE
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#else
|
||||
ESP_RETURN_ON_ERROR(lcd_module_init(), TAG, "display init failed");
|
||||
|
||||
if (timeout_ms == 0) {
|
||||
timeout_ms = LCD_PREVIEW_TIMEOUT_MS_DEFAULT;
|
||||
}
|
||||
|
||||
uint16_t *preview_pixels = NULL;
|
||||
uint16_t preview_w = 0;
|
||||
uint16_t preview_h = 0;
|
||||
esp_err_t convert_err = lcd_render_raster_to_rgb565(raster,
|
||||
raster_len,
|
||||
width,
|
||||
height,
|
||||
&preview_pixels,
|
||||
&preview_w,
|
||||
&preview_h,
|
||||
err,
|
||||
err_len);
|
||||
if (convert_err != ESP_OK) {
|
||||
return convert_err;
|
||||
}
|
||||
|
||||
if (!lcd_lock_take(timeout_ms)) {
|
||||
heap_caps_free(preview_pixels);
|
||||
lcd_fill_err(err, err_len, "display lock timeout");
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (s_lcd.demo_label != NULL) {
|
||||
lv_obj_del(s_lcd.demo_label);
|
||||
s_lcd.demo_label = NULL;
|
||||
}
|
||||
|
||||
if (s_lcd.preview_pixels != NULL) {
|
||||
heap_caps_free(s_lcd.preview_pixels);
|
||||
}
|
||||
s_lcd.preview_pixels = preview_pixels;
|
||||
|
||||
memset(&s_lcd.preview_dsc, 0, sizeof(s_lcd.preview_dsc));
|
||||
s_lcd.preview_dsc.header.always_zero = 0;
|
||||
s_lcd.preview_dsc.header.w = preview_w;
|
||||
s_lcd.preview_dsc.header.h = preview_h;
|
||||
s_lcd.preview_dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
|
||||
s_lcd.preview_dsc.data_size = (uint32_t)((size_t)preview_w * preview_h * sizeof(uint16_t));
|
||||
s_lcd.preview_dsc.data = (const uint8_t *)s_lcd.preview_pixels;
|
||||
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_set_style_bg_color(screen, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_img_set_src(s_lcd.preview_img, &s_lcd.preview_dsc);
|
||||
lv_obj_clear_flag(s_lcd.preview_img, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_center(s_lcd.preview_img);
|
||||
lv_refr_now(s_lcd.lv_disp);
|
||||
|
||||
lcd_lock_give();
|
||||
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;
|
||||
if (!lcd_lock_take(LCD_LOCK_TIMEOUT_MS)) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
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");
|
||||
if (s_lcd.preview_img != NULL) {
|
||||
lv_obj_add_flag(s_lcd.preview_img, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_set_style_bg_color(screen, lv_color_hex(0x1D3557), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, LV_PART_MAIN);
|
||||
|
||||
if (s_lcd.demo_label == NULL) {
|
||||
s_lcd.demo_label = lv_label_create(screen);
|
||||
}
|
||||
lv_label_set_text(s_lcd.demo_label, "LCD + LVGL ready");
|
||||
lv_obj_set_style_text_color(s_lcd.demo_label, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_center(s_lcd.demo_label);
|
||||
lv_refr_now(s_lcd.lv_disp);
|
||||
lcd_lock_give();
|
||||
|
||||
return ESP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -75,6 +75,13 @@ esp_err_t platform_direct_printer_gap_move(uint32_t timeout_ms, char *err, size_
|
||||
// ---------- display_st7789 ----------
|
||||
esp_err_t platform_display_init(void);
|
||||
esp_err_t platform_display_show_test_pattern(void);
|
||||
esp_err_t platform_display_show_raster_1bpp(const uint8_t *raster,
|
||||
size_t raster_len,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
uint32_t timeout_ms,
|
||||
char *err,
|
||||
size_t err_len);
|
||||
void platform_display_deinit(void);
|
||||
|
||||
// ---------- voice_audio ----------
|
||||
|
||||
@@ -16,3 +16,14 @@ esp_err_t platform_display_show_test_pattern(void)
|
||||
{
|
||||
return lcd_module_start_demo();
|
||||
}
|
||||
|
||||
esp_err_t platform_display_show_raster_1bpp(const uint8_t *raster,
|
||||
size_t raster_len,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
uint32_t timeout_ms,
|
||||
char *err,
|
||||
size_t err_len)
|
||||
{
|
||||
return lcd_module_show_raster_1bpp(raster, raster_len, width, height, timeout_ms, err, err_len);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,13 @@ dependencies:
|
||||
source:
|
||||
type: idf
|
||||
version: 5.5.1
|
||||
lvgl/lvgl:
|
||||
component_hash: d7c1ac037ae6e85d94897f807d6e7ba0946a83e720074fc95a4f6241da9f9f53
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 8.4.0
|
||||
direct_dependencies:
|
||||
- espressif/esp_audio_codec
|
||||
- espressif/esp_codec_dev
|
||||
@@ -74,6 +81,7 @@ direct_dependencies:
|
||||
- espressif/esp_websocket_client
|
||||
- espressif/libpng
|
||||
- idf
|
||||
manifest_hash: 5900d46fda5cdfbcdd8ddd277f3cf83d1ca7f79f4a98eb428297e57174c5181c
|
||||
- lvgl/lvgl
|
||||
manifest_hash: 4f3b822559c14ef8306b9123c3886e4a6b753913eb83fc226790b7e4d9dcd674
|
||||
target: esp32s3
|
||||
version: 2.0.0
|
||||
|
||||
@@ -19,3 +19,4 @@ dependencies:
|
||||
espressif/esp_audio_codec: ^2.4.1
|
||||
espressif/esp_jpeg: ">=1.0.2"
|
||||
espressif/libpng: ^1.6.55
|
||||
lvgl/lvgl: ^8.3.11
|
||||
|
||||
Reference in New Issue
Block a user