+ rearranged files
+ improved ui log + added image browser - image loading fails at the moment - arrangement of ui in image browser not checked
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
# ESP32 Image Viewer on LCD from SD
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This project utilizes an ELECROW ESP32 Display to read images from SD card and display them.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Insert SD card into the TF slot on the board. Flash the project to the ESP32. Use touch to switch between UI-Log and Image-Browser.
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
- ELECROW ESP32 5" HMI Display (800x480) RGB TFT Touchscreen compatible with LVGL
|
||||||
|
- USB-C cable to flash firmware
|
||||||
|
- optional but recommended:
|
||||||
|
- SD card
|
||||||
|
|
||||||
|
## Software
|
||||||
|
|
||||||
|
- ESP-IDF
|
||||||
|
- optional but recommended:
|
||||||
|
- VS Code with ESP-IDF extension
|
||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
idf_component_register(SRCS main.c lcd/lcd.c sd/sd.c
|
idf_component_register(SRCS main.c lcd/lcd.c sd/sd.c lcd/ui.c
|
||||||
PRIV_REQUIRES spi_flash esp_psram esp_lcd esp_driver_gpio esp_driver_i2c esp_driver_sdspi esp_driver_spi esp_lvgl_port esp_lcd_touch_gt911 fatfs sdmmc
|
PRIV_REQUIRES spi_flash esp_psram esp_lcd esp_driver_gpio esp_driver_i2c esp_driver_sdspi esp_driver_spi esp_lvgl_port esp_lcd_touch_gt911 fatfs sdmmc
|
||||||
INCLUDE_DIRS ".")
|
INCLUDE_DIRS "." "include")
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UI_VIEW_LOG,
|
||||||
|
UI_VIEW_IMAGE_BROWSER,
|
||||||
|
} ui_view_t;
|
||||||
|
|
||||||
|
void ui_log_append(const char *text);
|
||||||
|
void create_log_ui(void);
|
||||||
|
void create_image_browser_ui(void);
|
||||||
|
|
||||||
|
void ui_switch_view_to(ui_view_t view);
|
||||||
+4
-9
@@ -71,8 +71,7 @@ static esp_lcd_touch_handle_t touch_handle;
|
|||||||
static lv_display_t *lvgl_display;
|
static lv_display_t *lvgl_display;
|
||||||
static lv_indev_t *lvgl_touch_indev;
|
static lv_indev_t *lvgl_touch_indev;
|
||||||
|
|
||||||
static esp_err_t init_backlight(void)
|
static esp_err_t init_backlight(void){
|
||||||
{
|
|
||||||
const gpio_config_t backlight_config = {
|
const gpio_config_t backlight_config = {
|
||||||
.mode = GPIO_MODE_OUTPUT,
|
.mode = GPIO_MODE_OUTPUT,
|
||||||
.pin_bit_mask = 1ULL << LCD_GPIO_BACKLIGHT,
|
.pin_bit_mask = 1ULL << LCD_GPIO_BACKLIGHT,
|
||||||
@@ -83,8 +82,7 @@ static esp_err_t init_backlight(void)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t probe_gt911_address(i2c_master_bus_handle_t i2c_handle, uint32_t *dev_addr)
|
static esp_err_t probe_gt911_address(i2c_master_bus_handle_t i2c_handle, uint32_t *dev_addr){
|
||||||
{
|
|
||||||
const uint8_t addresses[] = {
|
const uint8_t addresses[] = {
|
||||||
ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS,
|
ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS,
|
||||||
ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP,
|
ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP,
|
||||||
@@ -265,9 +263,8 @@ static esp_err_t init_lvgl(void){
|
|||||||
lvgl_touch_indev = lvgl_port_add_touch(&touch_config);
|
lvgl_touch_indev = lvgl_port_add_touch(&touch_config);
|
||||||
ESP_RETURN_ON_FALSE(lvgl_touch_indev, ESP_FAIL, TAG, "LVGL touch add failed");
|
ESP_RETURN_ON_FALSE(lvgl_touch_indev, ESP_FAIL, TAG, "LVGL touch add failed");
|
||||||
ESP_LOGI(TAG, "LVGL touch input ready");
|
ESP_LOGI(TAG, "LVGL touch input ready");
|
||||||
} else {
|
|
||||||
ESP_LOGW(TAG, "LVGL touch input disabled");
|
|
||||||
}
|
}
|
||||||
|
else ESP_LOGW(TAG, "LVGL touch input disabled");
|
||||||
|
|
||||||
ESP_LOGI(TAG, "LVGL ready");
|
ESP_LOGI(TAG, "LVGL ready");
|
||||||
|
|
||||||
@@ -277,9 +274,7 @@ static esp_err_t init_lvgl(void){
|
|||||||
esp_err_t lcd_init(void){
|
esp_err_t lcd_init(void){
|
||||||
ESP_RETURN_ON_ERROR(init_rgb_panel(), TAG, "LCD panel init failed");
|
ESP_RETURN_ON_ERROR(init_rgb_panel(), TAG, "LCD panel init failed");
|
||||||
const esp_err_t touch_ret = init_touch();
|
const esp_err_t touch_ret = init_touch();
|
||||||
if (touch_ret != ESP_OK) {
|
if(touch_ret != ESP_OK) ESP_LOGW(TAG, "Continuing without touch: %s", esp_err_to_name(touch_ret));
|
||||||
ESP_LOGW(TAG, "Continuing without touch: %s", esp_err_to_name(touch_ret));
|
|
||||||
}
|
|
||||||
return init_lvgl();
|
return init_lvgl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+294
@@ -0,0 +1,294 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "lvgl.h"
|
||||||
|
#include "lcd/lcd.h"
|
||||||
|
#include "esp_lvgl_port.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "lcd/ui.h"
|
||||||
|
#include "sd/sd.h"
|
||||||
|
|
||||||
|
#define UI_LOG_MAX_LINES 41
|
||||||
|
#define UI_IMAGE_PATH_PREFIX "A:/sdcard/"
|
||||||
|
#define UI_IMAGE_PATH_MAX_LENGTH 160
|
||||||
|
#define UI_IMAGE_INFO_BAR_HEIGHT 42
|
||||||
|
|
||||||
|
static lv_obj_t *log_textarea = NULL;
|
||||||
|
static lv_obj_t *image_tileview = NULL;
|
||||||
|
static size_t log_line_length = 0;
|
||||||
|
static size_t image_browser_image_count = 0;
|
||||||
|
static size_t image_browser_current_index = 0;
|
||||||
|
static const char *TAG = "ui";
|
||||||
|
|
||||||
|
static ui_view_t current_view = UI_VIEW_LOG;
|
||||||
|
|
||||||
|
static void ui_reset_active_screen_locked(void){
|
||||||
|
lv_obj_t *screen = lv_screen_active();
|
||||||
|
lv_obj_clean(screen);
|
||||||
|
log_textarea = NULL;
|
||||||
|
image_tileview = NULL;
|
||||||
|
image_browser_image_count = 0;
|
||||||
|
image_browser_current_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ui_image_browser_set_index_locked(size_t image_index, lv_anim_enable_t anim_en){
|
||||||
|
if(image_tileview == NULL || image_browser_image_count == 0) return;
|
||||||
|
|
||||||
|
image_browser_current_index = image_index % image_browser_image_count;
|
||||||
|
lv_tileview_set_tile_by_index(image_tileview, 0, (uint32_t)image_browser_current_index, anim_en);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ui_image_browser_touch_event_cb(lv_event_t *event){
|
||||||
|
if(lv_event_get_code(event) != LV_EVENT_CLICKED) return;
|
||||||
|
ui_image_browser_set_index_locked(image_browser_current_index + 1, LV_ANIM_ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ui_image_browser_value_changed_event_cb(lv_event_t *event){
|
||||||
|
if(lv_event_get_code(event) != LV_EVENT_VALUE_CHANGED) return;
|
||||||
|
|
||||||
|
lv_obj_t *tileview = lv_event_get_current_target(event);
|
||||||
|
lv_obj_t *active_tile = lv_tileview_get_tile_active(tileview);
|
||||||
|
if(active_tile == NULL) return;
|
||||||
|
|
||||||
|
image_browser_current_index = (size_t)(uintptr_t)lv_obj_get_user_data(active_tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ui_char_equals_ignore_case(char left_char, char right_char){
|
||||||
|
if(left_char >= 'A' && left_char <= 'Z') left_char = (char)(left_char + ('a' - 'A'));
|
||||||
|
if(right_char >= 'A' && right_char <= 'Z') right_char = (char)(right_char + ('a' - 'A'));
|
||||||
|
return left_char == right_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ui_has_extension(const char *filename, const char *extension){
|
||||||
|
if(filename == NULL || extension == NULL) return false;
|
||||||
|
|
||||||
|
const size_t filename_length = strlen(filename);
|
||||||
|
const size_t extension_length = strlen(extension);
|
||||||
|
if(filename_length < extension_length) return false;
|
||||||
|
|
||||||
|
const char *filename_extension = filename + filename_length - extension_length;
|
||||||
|
for(size_t char_index = 0; char_index < extension_length; char_index++){
|
||||||
|
if(!ui_char_equals_ignore_case(filename_extension[char_index], extension[char_index])) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ui_is_image_file(const char *filename){
|
||||||
|
return ui_has_extension(filename, ".bmp") ||
|
||||||
|
ui_has_extension(filename, ".jpg") ||
|
||||||
|
ui_has_extension(filename, ".jpeg") ||
|
||||||
|
ui_has_extension(filename, ".png");
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ui_count_sd_images(void){
|
||||||
|
const size_t file_count = sd_get_file_count();
|
||||||
|
size_t image_count = 0;
|
||||||
|
|
||||||
|
for(size_t file_index = 0; file_index < file_count; file_index++){
|
||||||
|
const char *filename = sd_get_next_file();
|
||||||
|
if(ui_is_image_file(filename)) image_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return image_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ui_create_empty_image_browser_locked(lv_obj_t *screen){
|
||||||
|
lv_obj_t *label = lv_label_create(screen);
|
||||||
|
lv_label_set_text(label, "No images found on SD card");
|
||||||
|
lv_obj_set_style_text_color(label, lv_color_hex(0xdde7ef), 0);
|
||||||
|
lv_obj_center(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_dir_t ui_get_tile_directions(size_t image_index, size_t image_count){
|
||||||
|
if(image_count <= 1) return LV_DIR_NONE;
|
||||||
|
if(image_index == 0) return LV_DIR_BOTTOM;
|
||||||
|
if(image_index + 1 == image_count) return LV_DIR_TOP;
|
||||||
|
return (lv_dir_t)(LV_DIR_TOP | LV_DIR_BOTTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ui_create_image_tile_locked(lv_obj_t *tile, const char *filename, size_t image_index, size_t image_count){
|
||||||
|
lv_obj_set_style_bg_color(tile, lv_color_hex(0x070a0d), 0);
|
||||||
|
lv_obj_set_style_pad_all(tile, 0, 0);
|
||||||
|
lv_obj_remove_flag(tile, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
|
|
||||||
|
lv_obj_t *image_frame = lv_obj_create(tile);
|
||||||
|
lv_obj_set_size(image_frame, LV_PCT(100), LV_PCT(100));
|
||||||
|
lv_obj_set_style_bg_color(image_frame, lv_color_black(), 0);
|
||||||
|
lv_obj_set_style_border_width(image_frame, 0, 0);
|
||||||
|
lv_obj_set_style_radius(image_frame, 0, 0);
|
||||||
|
lv_obj_set_style_pad_all(image_frame, 0, 0);
|
||||||
|
lv_obj_remove_flag(image_frame, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
|
lv_obj_center(image_frame);
|
||||||
|
|
||||||
|
lv_obj_t *image = lv_image_create(image_frame);
|
||||||
|
lv_obj_set_size(image, LV_PCT(100), LV_PCT(100));
|
||||||
|
lv_image_set_inner_align(image, LV_IMAGE_ALIGN_CONTAIN);
|
||||||
|
|
||||||
|
char image_source[UI_IMAGE_PATH_MAX_LENGTH];
|
||||||
|
snprintf(image_source, sizeof(image_source), "%s%s", UI_IMAGE_PATH_PREFIX, filename);
|
||||||
|
lv_image_set_src(image, image_source);
|
||||||
|
lv_obj_center(image);
|
||||||
|
|
||||||
|
lv_obj_t *info_bar = lv_obj_create(tile);
|
||||||
|
lv_obj_set_size(info_bar, LV_PCT(100), UI_IMAGE_INFO_BAR_HEIGHT);
|
||||||
|
lv_obj_align(info_bar, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||||
|
lv_obj_set_style_bg_color(info_bar, lv_color_hex(0x101418), 0);
|
||||||
|
lv_obj_set_style_bg_opa(info_bar, LV_OPA_80, 0);
|
||||||
|
lv_obj_set_style_border_width(info_bar, 0, 0);
|
||||||
|
lv_obj_set_style_radius(info_bar, 0, 0);
|
||||||
|
lv_obj_set_style_pad_hor(info_bar, 14, 0);
|
||||||
|
lv_obj_set_style_pad_ver(info_bar, 0, 0);
|
||||||
|
lv_obj_remove_flag(info_bar, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
|
|
||||||
|
lv_obj_t *caption = lv_label_create(info_bar);
|
||||||
|
lv_label_set_long_mode(caption, LV_LABEL_LONG_DOT);
|
||||||
|
lv_obj_set_width(caption, LV_PCT(100));
|
||||||
|
lv_obj_set_style_text_color(caption, lv_color_hex(0xdde7ef), 0);
|
||||||
|
lv_label_set_text_fmt(caption, "%u/%u %s", (unsigned int)(image_index + 1), (unsigned int)image_count, filename);
|
||||||
|
lv_obj_center(caption);
|
||||||
|
|
||||||
|
if(lv_image_get_src_width(image) <= 0 || lv_image_get_src_height(image) <= 0){
|
||||||
|
lv_obj_t *error_label = lv_label_create(tile);
|
||||||
|
lv_label_set_text(error_label, "Image cannot be loaded");
|
||||||
|
lv_obj_set_style_text_color(error_label, lv_color_hex(0xffd166), 0);
|
||||||
|
lv_obj_align(error_label, LV_ALIGN_CENTER, 0, -18);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ui_create_image_browser_tiles_locked(size_t image_count){
|
||||||
|
const size_t file_count = sd_get_file_count();
|
||||||
|
size_t image_index = 0;
|
||||||
|
|
||||||
|
for(size_t file_index = 0; file_index < file_count && image_index < image_count; file_index++){
|
||||||
|
const char *filename = sd_get_next_file();
|
||||||
|
if(!ui_is_image_file(filename)) continue;
|
||||||
|
|
||||||
|
lv_obj_t *tile = lv_tileview_add_tile(image_tileview, 0, (uint32_t)image_index, ui_get_tile_directions(image_index, image_count));
|
||||||
|
lv_obj_set_user_data(tile, (void *)(uintptr_t)image_index);
|
||||||
|
lv_obj_add_flag(tile, LV_OBJ_FLAG_CLICKABLE);
|
||||||
|
lv_obj_add_event_cb(tile, ui_image_browser_touch_event_cb, LV_EVENT_CLICKED, NULL);
|
||||||
|
ui_create_image_tile_locked(tile, filename, image_index, image_count);
|
||||||
|
image_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ui_log_delete_first_line(void){
|
||||||
|
lvgl_port_lock(0);
|
||||||
|
size_t cursor_pos = lv_textarea_get_cursor_pos(log_textarea);
|
||||||
|
lv_textarea_set_cursor_pos(log_textarea, 0);
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
const char *log_text = lv_textarea_get_text(log_textarea);
|
||||||
|
if(log_text[0] == '\0') break;
|
||||||
|
|
||||||
|
char first_char = log_text[0];
|
||||||
|
lv_textarea_delete_char_forward(log_textarea);
|
||||||
|
|
||||||
|
if(first_char == '\n') break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_textarea_set_cursor_pos(log_textarea, cursor_pos);
|
||||||
|
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_log_append(const char *text){
|
||||||
|
if(log_textarea == NULL || text == NULL) return;
|
||||||
|
|
||||||
|
lvgl_port_lock(0);
|
||||||
|
lv_textarea_add_text(log_textarea, text);
|
||||||
|
lv_textarea_add_text(log_textarea, "\n");
|
||||||
|
lv_textarea_set_cursor_pos(log_textarea, LV_TEXTAREA_CURSOR_LAST);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
|
||||||
|
log_line_length++;
|
||||||
|
|
||||||
|
while(log_line_length > UI_LOG_MAX_LINES){
|
||||||
|
ui_log_delete_first_line();
|
||||||
|
log_line_length--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_log_ui(void){
|
||||||
|
ESP_LOGI(TAG, "Creating log UI");
|
||||||
|
lvgl_port_lock(0);
|
||||||
|
ui_reset_active_screen_locked();
|
||||||
|
|
||||||
|
lv_obj_t *screen = lv_screen_active();
|
||||||
|
lv_obj_set_style_bg_color(screen, lv_color_hex(0x101418), 0);
|
||||||
|
|
||||||
|
lv_obj_t *title = lv_label_create(screen);
|
||||||
|
lv_label_set_text(title, "SD Image Viewer");
|
||||||
|
lv_obj_set_style_text_color(title, lv_color_white(), 0);
|
||||||
|
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 14);
|
||||||
|
|
||||||
|
if(log_textarea == NULL){
|
||||||
|
log_textarea = lv_textarea_create(screen);
|
||||||
|
lv_obj_set_size(log_textarea, 440, 730);
|
||||||
|
lv_obj_align(log_textarea, LV_ALIGN_TOP_LEFT, 20, 40);
|
||||||
|
lv_textarea_set_one_line(log_textarea, false);
|
||||||
|
lv_textarea_set_cursor_click_pos(log_textarea, false);
|
||||||
|
lv_textarea_set_text(log_textarea, "");
|
||||||
|
lv_obj_set_style_bg_color(log_textarea, lv_color_hex(0x182028), 0);
|
||||||
|
lv_obj_set_style_text_color(log_textarea, lv_color_hex(0xdde7ef), 0);
|
||||||
|
lv_obj_set_style_border_color(log_textarea, lv_color_hex(0x4b6478), 0);
|
||||||
|
lv_obj_set_style_radius(log_textarea, 4, 0);
|
||||||
|
lv_obj_set_style_pad_all(log_textarea, 12, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lvgl_port_unlock();
|
||||||
|
|
||||||
|
ui_log_append("Boot UI ready");
|
||||||
|
current_view = UI_VIEW_LOG;
|
||||||
|
ESP_LOGI(TAG, "Log UI created");
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_image_browser_ui(void){
|
||||||
|
ESP_LOGI(TAG, "Creating image browser UI");
|
||||||
|
const size_t image_count = ui_count_sd_images();
|
||||||
|
|
||||||
|
lvgl_port_lock(0);
|
||||||
|
ui_reset_active_screen_locked();
|
||||||
|
|
||||||
|
lv_obj_t *screen = lv_screen_active();
|
||||||
|
lv_obj_set_style_bg_color(screen, lv_color_hex(0x070a0d), 0);
|
||||||
|
|
||||||
|
if(image_count == 0) ui_create_empty_image_browser_locked(screen);
|
||||||
|
else{
|
||||||
|
image_tileview = lv_tileview_create(screen);
|
||||||
|
lv_obj_set_size(image_tileview, LV_PCT(100), LV_PCT(100));
|
||||||
|
lv_obj_set_style_bg_color(image_tileview, lv_color_hex(0x070a0d), 0);
|
||||||
|
lv_obj_set_style_border_width(image_tileview, 0, 0);
|
||||||
|
lv_obj_set_style_pad_all(image_tileview, 0, 0);
|
||||||
|
lv_obj_set_scrollbar_mode(image_tileview, LV_SCROLLBAR_MODE_OFF);
|
||||||
|
lv_obj_add_event_cb(image_tileview, ui_image_browser_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||||
|
image_browser_image_count = image_count;
|
||||||
|
|
||||||
|
ui_create_image_browser_tiles_locked(image_count);
|
||||||
|
ui_image_browser_set_index_locked(0, LV_ANIM_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_view = UI_VIEW_IMAGE_BROWSER;
|
||||||
|
lvgl_port_unlock();
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Image browser UI created with %u images", (unsigned int)image_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_switch_view_to(ui_view_t view){
|
||||||
|
if(view == current_view) return;
|
||||||
|
|
||||||
|
switch(view){
|
||||||
|
case UI_VIEW_LOG:
|
||||||
|
create_log_ui();
|
||||||
|
break;
|
||||||
|
case UI_VIEW_IMAGE_BROWSER:
|
||||||
|
create_image_browser_ui();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGW(TAG, "Unknown UI view: %d", view);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-58
@@ -1,67 +1,28 @@
|
|||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
#include "lcd/lcd.h"
|
|
||||||
#include "sd/sd.h"
|
#include "sd/sd.h"
|
||||||
#include "lvgl.h"
|
#include "lcd/lcd.h"
|
||||||
|
#include "lcd/ui.h"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
|
||||||
static const char *TAG = "app";
|
static const char *TAG = "app";
|
||||||
static lv_obj_t *log_textarea = NULL;
|
|
||||||
|
|
||||||
static void ui_log_append(const char *text)
|
void app_main(void){
|
||||||
{
|
|
||||||
if(log_textarea == NULL || text == NULL) return;
|
|
||||||
|
|
||||||
lvgl_port_lock(0);
|
|
||||||
lv_textarea_add_text(log_textarea, text);
|
|
||||||
lv_textarea_add_text(log_textarea, "\n");
|
|
||||||
lv_textarea_set_cursor_pos(log_textarea, LV_TEXTAREA_CURSOR_LAST);
|
|
||||||
lvgl_port_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void create_log_ui(void)
|
|
||||||
{
|
|
||||||
lv_obj_t *screen = lv_screen_active();
|
|
||||||
lv_obj_set_style_bg_color(screen, lv_color_hex(0x101418), 0);
|
|
||||||
|
|
||||||
lv_obj_t *title = lv_label_create(screen);
|
|
||||||
lv_label_set_text(title, "SD Image Viewer");
|
|
||||||
lv_obj_set_style_text_color(title, lv_color_white(), 0);
|
|
||||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 14);
|
|
||||||
|
|
||||||
log_textarea = lv_textarea_create(screen);
|
|
||||||
lv_obj_set_size(log_textarea, lv_pct(92), lv_pct(84));
|
|
||||||
lv_obj_align(log_textarea, LV_ALIGN_BOTTOM_MID, 0, -14);
|
|
||||||
lv_textarea_set_one_line(log_textarea, false);
|
|
||||||
lv_textarea_set_cursor_click_pos(log_textarea, false);
|
|
||||||
lv_textarea_set_text(log_textarea, "");
|
|
||||||
lv_obj_set_style_bg_color(log_textarea, lv_color_hex(0x182028), 0);
|
|
||||||
lv_obj_set_style_text_color(log_textarea, lv_color_hex(0xdde7ef), 0);
|
|
||||||
lv_obj_set_style_border_color(log_textarea, lv_color_hex(0x4b6478), 0);
|
|
||||||
lv_obj_set_style_radius(log_textarea, 4, 0);
|
|
||||||
lv_obj_set_style_pad_all(log_textarea, 12, 0);
|
|
||||||
|
|
||||||
lv_textarea_add_text(log_textarea, "Boot UI ready\n");
|
|
||||||
lv_textarea_set_cursor_pos(log_textarea, LV_TEXTAREA_CURSOR_LAST);
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_main(void)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Start display application");
|
ESP_LOGI(TAG, "Start display application");
|
||||||
ESP_ERROR_CHECK(lcd_init());
|
ESP_ERROR_CHECK(lcd_init());
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Creating log UI");
|
ESP_LOGI(TAG, "Creating log UI");
|
||||||
lvgl_port_lock(0);
|
|
||||||
create_log_ui();
|
create_log_ui();
|
||||||
lvgl_port_unlock();
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Initializing SD card");
|
ESP_LOGI(TAG, "Initializing SD card");
|
||||||
ui_log_append("Initializing SD card...");
|
ui_log_append("\nInitializing SD card...");
|
||||||
sd_init();
|
sd_init();
|
||||||
print_sd_card_info();
|
print_sd_card_info();
|
||||||
ui_log_append("SD initialization done");
|
ui_log_append("SD initialization done");
|
||||||
ESP_LOGI(TAG, "SD card initialization complete");
|
ESP_LOGI(TAG, "SD card initialization complete");
|
||||||
|
|
||||||
|
ui_log_append("\nListing files in root directory:");
|
||||||
size_t file_count = sd_get_file_count();
|
size_t file_count = sd_get_file_count();
|
||||||
ESP_LOGI(TAG, "Found %d files in root directory", file_count);
|
ESP_LOGI(TAG, "Found %d files in root directory", file_count);
|
||||||
const char* filename = NULL;
|
const char* filename = NULL;
|
||||||
@@ -71,19 +32,13 @@ void app_main(void)
|
|||||||
char line[96];
|
char line[96];
|
||||||
snprintf(line, sizeof(line), "Found file: %s", filename);
|
snprintf(line, sizeof(line), "Found file: %s", filename);
|
||||||
ui_log_append(line);
|
ui_log_append(line);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
ui_log_append("Done listing files in root directory");
|
||||||
FILE* file = sd_open_write("test.txt");
|
|
||||||
if(file != NULL){
|
|
||||||
fprintf(file, "Hello, SD card!\n");
|
|
||||||
sd_close_file(file);
|
|
||||||
ui_log_append("Wrote test.txt");
|
|
||||||
} else {
|
|
||||||
ui_log_append("Failed to open test.txt for writing");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
sd_destroy();
|
ui_switch_view_to(UI_VIEW_IMAGE_BROWSER);
|
||||||
ui_log_append("SD card unmounted");
|
|
||||||
|
// sd_destroy();
|
||||||
|
// ui_log_append("\nSD card unmounted");
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -71,16 +71,14 @@ void sd_init(void){
|
|||||||
ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
|
ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
|
||||||
|
|
||||||
if(ret != ESP_OK){
|
if(ret != ESP_OK){
|
||||||
if(ret == ESP_FAIL) ESP_LOGE(TAG, "Failed to mount filesystem.");
|
if(ret == ESP_FAIL) ESP_LOGE(TAG, "Failed to mount filesystem."); else ESP_LOGE(TAG, "Failed to initialize the card (%s). ", esp_err_to_name(ret));
|
||||||
else ESP_LOGE(TAG, "Failed to initialize the card (%s). ", esp_err_to_name(ret));
|
|
||||||
spi_bus_free(host.slot);
|
spi_bus_free(host.slot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "SD card initialized");
|
ESP_LOGI(TAG, "SD card initialized");
|
||||||
|
|
||||||
if(get_top_level_files() == ESP_OK) ESP_LOGI(TAG, "Found %d files in root directory", _file_count);
|
if(get_top_level_files() == ESP_OK) ESP_LOGI(TAG, "Found %d files in root directory", _file_count); else ESP_LOGW(TAG, "No files found in root directory");
|
||||||
else ESP_LOGW(TAG, "No files found in root directory");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_sd_card_info(void){
|
void print_sd_card_info(void){
|
||||||
|
|||||||
@@ -3180,9 +3180,12 @@ CONFIG_LV_USE_GRID=y
|
|||||||
# 3rd Party Libraries
|
# 3rd Party Libraries
|
||||||
#
|
#
|
||||||
# default:
|
# default:
|
||||||
CONFIG_LV_FS_DEFAULT_DRIVER_LETTER=0
|
CONFIG_LV_FS_DEFAULT_DRIVER_LETTER=65
|
||||||
|
CONFIG_LV_USE_FS_STDIO=y
|
||||||
# default:
|
# default:
|
||||||
# CONFIG_LV_USE_FS_STDIO is not set
|
CONFIG_LV_FS_STDIO_LETTER=65
|
||||||
|
CONFIG_LV_FS_STDIO_PATH=""
|
||||||
|
CONFIG_LV_FS_STDIO_CACHE_SIZE=0
|
||||||
# default:
|
# default:
|
||||||
# CONFIG_LV_USE_FS_POSIX is not set
|
# CONFIG_LV_USE_FS_POSIX is not set
|
||||||
# default:
|
# default:
|
||||||
@@ -3207,8 +3210,7 @@ CONFIG_LV_FS_DEFAULT_DRIVER_LETTER=0
|
|||||||
# CONFIG_LV_USE_LIBPNG is not set
|
# CONFIG_LV_USE_LIBPNG is not set
|
||||||
# default:
|
# default:
|
||||||
# CONFIG_LV_USE_BMP is not set
|
# CONFIG_LV_USE_BMP is not set
|
||||||
# default:
|
CONFIG_LV_USE_TJPGD=y
|
||||||
# CONFIG_LV_USE_TJPGD is not set
|
|
||||||
# default:
|
# default:
|
||||||
# CONFIG_LV_USE_LIBJPEG_TURBO is not set
|
# CONFIG_LV_USE_LIBJPEG_TURBO is not set
|
||||||
# default:
|
# default:
|
||||||
|
|||||||
Reference in New Issue
Block a user