Feature: 支持 LVGL 作为嵌入式显示屏的底层。 #7

Merged
Ivan merged 5 commits from feature/lvgl into master 2023-05-03 21:04:25 +08:00
7 changed files with 316 additions and 22 deletions
Showing only changes of commit b7476428a2 - Show all commits

View File

@ -11,11 +11,11 @@ dependencies:
type: idf type: idf
version: 5.0.1 version: 5.0.1
lvgl/lvgl: lvgl/lvgl:
component_hash: 2567762b19953712ee38789ad8f8de57ad1f6e39283adefbbfc7184ffe662831 component_hash: 0f2006e7b800eee17b73ed4f92ffbaa76d61c02ba4779ec9efbcd5f453bb0102
source: source:
service_url: https://api.components.espressif.com/ service_url: https://api.components.espressif.com/
type: service type: service
version: 8.2.0 version: 8.3.6~1
manifest_hash: bef1e4573234ace0f846d8355b65d9ec82a4aeada7c2fa638efbec574f134e54 manifest_hash: 9a88337b9db92c26041847f5fd4efc58df1dcf0e9c6b8758da96aaac2e63c2a2
target: esp32c3 target: esp32c3
version: 1.0.0 version: 1.0.0

View File

@ -20,5 +20,6 @@ idf_component_register(
"led_strip_encoder/led_strip_encoder.c" "led_strip_encoder/led_strip_encoder.c"
"gui.c" "gui.c"
"lvgl_demo_ui.c" "lvgl_demo_ui.c"
"app_icon_8.c"
INCLUDE_DIRS "." INCLUDE_DIRS "."
) )

157
main/app_icon_8.c Normal file
View File

@ -0,0 +1,157 @@
/*******************************************************************************
* Size: 8 px
* Bpp: 1
* Opts:
******************************************************************************/
#pragma once
#include "lvgl.h"
#ifndef APP_ICON_8
#define APP_ICON_8 1
#endif
#if APP_ICON_8
/*-----------------
* BITMAPS
*----------------*/
/*Store the image of the glyphs*/
static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
/* U+E1CB "" */
0x38, 0x31, 0x88, 0xfa, 0x49, 0x54, 0x44, 0x10, 0xf8,
/* U+E1CC "" */
0x80, 0x1f, 0xa, 0x22, 0x6b, 0xd4, 0x44, 0xd0, 0xc8, 0x1,
/* U+E29E "" */
0xe, 0x4, 0xa8, 0x32, 0x18, 0xe, 0xd, 0x8c, 0x7c,
/* U+F1EB "" */
0x1e, 0x18, 0x68, 0x4, 0x78, 0x21, 0x0, 0x0, 0xc0, 0x0,
/* U+F6AA "" */
0xc0,
/* U+F6AB "" */
0x79, 0x8, 0x1, 0x80};
/*---------------------
* GLYPH DESCRIPTION
*--------------------*/
static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 0,
.adv_w = 0,
.box_w = 0,
.box_h = 0,
.ofs_x = 0,
.ofs_y = 0} /* id = 0 reserved */,
{.bitmap_index = 0,
.adv_w = 160,
.box_w = 10,
.box_h = 7,
.ofs_x = 0,
.ofs_y = 0},
{.bitmap_index = 9,
.adv_w = 160,
.box_w = 10,
.box_h = 8,
.ofs_x = 0,
.ofs_y = -1},
{.bitmap_index = 19,
.adv_w = 128,
.box_w = 9,
.box_h = 8,
.ofs_x = 0,
.ofs_y = -1},
{.bitmap_index = 28,
.adv_w = 160,
.box_w = 10,
.box_h = 8,
.ofs_x = 0,
.ofs_y = -1},
{.bitmap_index = 38,
.adv_w = 32,
.box_w = 2,
.box_h = 2,
.ofs_x = 4,
.ofs_y = -1},
{.bitmap_index = 39,
.adv_w = 112,
.box_w = 7,
.box_h = 4,
.ofs_x = 2,
.ofs_y = 0}};
/*---------------------
* CHARACTER MAPPING
*--------------------*/
static const uint16_t unicode_list_0[] = {0x0, 0x1, 0xd3,
0x1020, 0x14df, 0x14e0};
/*Collect the unicode lists and glyph_id offsets*/
static const lv_font_fmt_txt_cmap_t cmaps[] = {
{.range_start = 57803,
.range_length = 5345,
.glyph_id_start = 1,
.unicode_list = unicode_list_0,
.glyph_id_ofs_list = NULL,
.list_length = 6,
.type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY}};
/*--------------------
* ALL CUSTOM DATA
*--------------------*/
#if LV_VERSION_CHECK(8, 0, 0)
/*Store all the custom data of the font*/
static lv_font_fmt_txt_glyph_cache_t cache;
static const lv_font_fmt_txt_dsc_t font_dsc = {
#else
static lv_font_fmt_txt_dsc_t font_dsc = {
#endif
.glyph_bitmap = glyph_bitmap,
.glyph_dsc = glyph_dsc,
.cmaps = cmaps,
.kern_dsc = NULL,
.kern_scale = 0,
.cmap_num = 1,
.bpp = 1,
.kern_classes = 0,
.bitmap_format = 0,
#if LV_VERSION_CHECK(8, 0, 0)
.cache = &cache
#endif
};
/*-----------------
* PUBLIC FONT
*----------------*/
/*Initialize a public general font descriptor*/
#if LV_VERSION_CHECK(8, 0, 0)
const lv_font_t app_icon_8 = {
#else
lv_font_t app_icon_8 = {
#endif
.get_glyph_dsc =
lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
.get_glyph_bitmap =
lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
.line_height = 8, /*The maximum line height required by the font*/
.base_line = 1, /*Baseline measured from the bottom of the line*/
#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0)
.subpx = LV_FONT_SUBPX_NONE,
#endif
#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8
.underline_position = -1,
.underline_thickness = 0,
#endif
.dsc = &font_dsc /*The custom font data. Will be accessed by
`get_glyph_bitmap/dsc` */
};
#endif /*#if APP_ICON_8*/

View File

@ -6,6 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include "app_icon_8.c"
#include "ch1116.c" #include "ch1116.c"
#include "driver/i2c.h" #include "driver/i2c.h"
#include "esp_err.h" #include "esp_err.h"
@ -19,10 +20,6 @@ static const char *GUI_TAG = "LVGL_GUI";
#define I2C_HOST 0 #define I2C_HOST 0
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// Please update the following configuration according to your
/// LCD spec //////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (400 * 1000) #define EXAMPLE_LCD_PIXEL_CLOCK_HZ (400 * 1000)
#define EXAMPLE_LCD_H_RES CH1116_WIDTH #define EXAMPLE_LCD_H_RES CH1116_WIDTH
@ -30,6 +27,21 @@ static const char *GUI_TAG = "LVGL_GUI";
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2 #define EXAMPLE_LVGL_TICK_PERIOD_MS 2
// EF 9A AA
#define APP_WIFI_WEAK_SYMBOL "\xEF\x9A\xAA"
// EF 9A AB
#define APP_WIFI_FAIR_SYMBOL "\xEF\x9A\xAB"
// EF 87 AB
#define APP_WIFI_GOOD_SYMBOL "\xEF\x87\xAB"
// EE 87 8C
#define APP_CONNECTED_SYMBOL "\xEE\x87\x8C"
// EE 87 8B
#define APP_DISCONNECTED_SYMBOL "\xEE\x87\x8B"
// EE 8A 9E
#define APP_TIMER_SYMBOL "\xEE\x8A\x9E"
extern void example_lvgl_demo_ui(lv_disp_t *disp); extern void example_lvgl_demo_ui(lv_disp_t *disp);
static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area,
@ -56,6 +68,15 @@ static void example_lvgl_set_px_cb(lv_disp_drv_t *disp_drv, uint8_t *buf,
} }
} }
static lv_obj_t *wifi_label;
static lv_anim_t wifi_animate;
static lv_obj_t *timer_label;
static lv_anim_t timer_animate;
static lv_obj_t *desktop_label;
static lv_anim_t desktop_animate;
static void example_lvgl_rounder(lv_disp_drv_t *disp_drv, lv_area_t *area) { static void example_lvgl_rounder(lv_disp_drv_t *disp_drv, lv_area_t *area) {
area->y1 = area->y1 & (~0x7); area->y1 = area->y1 & (~0x7);
area->y2 = area->y2 | 0x7; area->y2 = area->y2 | 0x7;
@ -70,6 +91,86 @@ static void set_value(void *bar, int32_t v) {
lv_bar_set_value(bar, v, LV_ANIM_OFF); lv_bar_set_value(bar, v, LV_ANIM_OFF);
} }
static void set_visible(void *obj, int32_t v) {
if (v) {
lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN);
} else {
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
}
}
static void set_obj_blink_animate(lv_obj_t *obj, lv_anim_t *a) {
lv_anim_init(a);
lv_anim_set_exec_cb(a, set_visible);
lv_anim_set_time(a, 100);
lv_anim_set_playback_time(a, 100);
lv_anim_set_playback_delay(a, 200);
lv_anim_set_repeat_delay(a, 200);
lv_anim_set_values(a, 0, 1);
lv_anim_set_var(a, obj);
lv_anim_set_repeat_count(a, LV_ANIM_REPEAT_INFINITE);
lv_anim_start(a);
}
static void change_wifi_icon(void *obj, int32_t v) {
switch (v) {
case 0:
lv_label_set_text(obj, APP_WIFI_WEAK_SYMBOL);
break;
case 1:
lv_label_set_text(obj, APP_WIFI_FAIR_SYMBOL);
break;
case 2:
lv_label_set_text(obj, APP_WIFI_GOOD_SYMBOL);
break;
default:
ESP_LOGW(GUI_TAG, "Unknown wifi strength: %ld", v);
break;
}
}
static void gui_set_wifi_connecting() {
lv_obj_clear_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
lv_anim_init(&wifi_animate);
lv_anim_set_exec_cb(&wifi_animate, change_wifi_icon);
lv_anim_set_time(&wifi_animate, 300);
lv_anim_set_repeat_delay(&wifi_animate, 300);
lv_anim_set_values(&wifi_animate, 0, 2);
lv_anim_set_var(&wifi_animate, wifi_label);
lv_anim_set_repeat_count(&wifi_animate, LV_ANIM_REPEAT_INFINITE);
lv_anim_start(&wifi_animate);
}
static void gui_set_wifi_connected() {
lv_anim_del(wifi_label, NULL);
lv_obj_clear_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
lv_label_set_text(wifi_label, APP_WIFI_GOOD_SYMBOL);
}
static void gui_set_wifi_disconnected() {
lv_anim_del(&wifi_label, NULL);
lv_obj_clear_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
lv_label_set_text(wifi_label, APP_WIFI_WEAK_SYMBOL);
}
static void gui_set_server_connecting() {
set_obj_blink_animate(desktop_label, &desktop_animate);
}
static void gui_set_server_connected() {
lv_anim_del(&desktop_label, NULL);
lv_obj_clear_flag(desktop_label, LV_OBJ_FLAG_HIDDEN);
lv_label_set_text(desktop_label, APP_CONNECTED_SYMBOL);
}
static void gui_set_server_disconnected() {
lv_anim_del(&desktop_label, NULL);
lv_obj_clear_flag(desktop_label, LV_OBJ_FLAG_HIDDEN);
lv_label_set_text(desktop_label, APP_DISCONNECTED_SYMBOL);
}
void lv_example_bar_6(lv_obj_t *src) { void lv_example_bar_6(lv_obj_t *src) {
static lv_style_t style_bar; static lv_style_t style_bar;
lv_style_init(&style_bar); lv_style_init(&style_bar);
@ -104,6 +205,38 @@ void lv_example_bar_6(lv_obj_t *src) {
lv_anim_start(&a); lv_anim_start(&a);
} }
void gui_status_bar_create(lv_obj_t *scr) {
// wifi icon
wifi_label = lv_label_create(scr);
lv_label_set_long_mode(wifi_label, LV_LABEL_LONG_SCROLL_CIRCULAR);
lv_label_set_text(wifi_label, APP_WIFI_GOOD_SYMBOL);
lv_obj_set_width(wifi_label, 10);
lv_obj_align(wifi_label, LV_ALIGN_OUT_TOP_LEFT, 0, 0);
lv_obj_set_style_text_color(wifi_label, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_text_font(wifi_label, &app_icon_8, LV_PART_MAIN);
lv_obj_add_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
// timer icon
timer_label = lv_label_create(scr);
lv_label_set_long_mode(timer_label, LV_LABEL_LONG_SCROLL_CIRCULAR);
lv_label_set_text(timer_label, APP_TIMER_SYMBOL);
lv_obj_set_width(timer_label, 10);
lv_obj_align(timer_label, LV_ALIGN_OUT_TOP_LEFT, 12, 0);
lv_obj_set_style_text_color(timer_label, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_text_font(timer_label, &app_icon_8, LV_PART_MAIN);
lv_obj_add_flag(timer_label, LV_OBJ_FLAG_HIDDEN);
// desktop icon
desktop_label = lv_label_create(scr);
lv_label_set_long_mode(desktop_label, LV_LABEL_LONG_SCROLL_CIRCULAR);
lv_label_set_text(desktop_label, APP_CONNECTED_SYMBOL);
lv_obj_set_width(desktop_label, 10);
lv_obj_align(desktop_label, LV_ALIGN_OUT_TOP_LEFT, 24, 0);
lv_obj_set_style_text_color(desktop_label, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_text_font(desktop_label, &app_icon_8, LV_PART_MAIN);
lv_obj_add_flag(desktop_label, LV_OBJ_FLAG_HIDDEN);
}
void example_lvgl_demo_ui(lv_disp_t *disp) { void example_lvgl_demo_ui(lv_disp_t *disp) {
lv_obj_t *scr = lv_disp_get_scr_act(disp); lv_obj_t *scr = lv_disp_get_scr_act(disp);
@ -113,9 +246,11 @@ void example_lvgl_demo_ui(lv_disp_t *disp) {
*/ */
lv_label_set_text(label, "Hello Espressif, Hello LVGL."); lv_label_set_text(label, "Hello Espressif, Hello LVGL.");
lv_obj_set_width(label, 120); lv_obj_set_width(label, 120);
lv_obj_center(label); lv_obj_align(label, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
lv_example_bar_6(scr); lv_example_bar_6(scr);
gui_status_bar_create(scr);
} }
static void gui_tick(void *pvParameters) { static void gui_tick(void *pvParameters) {
@ -128,6 +263,7 @@ static void gui_tick(void *pvParameters) {
lv_timer_handler(); lv_timer_handler();
} }
} }
void gui_main(void) { void gui_main(void) {
static lv_disp_draw_buf_t static lv_disp_draw_buf_t
disp_buf; // contains internal graphic buffer(s) called draw buffer(s) disp_buf; // contains internal graphic buffer(s) called draw buffer(s)

View File

@ -1,6 +1,6 @@
## IDF Component Manager Manifest File ## IDF Component Manager Manifest File
dependencies: dependencies:
lvgl/lvgl: "~8.2.0" lvgl/lvgl: "^8.3.6~1"
espressif/mdns: "^1.0.9" espressif/mdns: "^1.0.9"
## Required IDF version ## Required IDF version
idf: idf:

View File

@ -23,15 +23,19 @@ void app_main(void) {
app_nvs_init(); app_nvs_init();
light_init_strip(); light_init_strip();
gpio_install_isr_service(0); // gpio_install_isr_service(0);
init_i2c(); init_i2c();
i2c_check_slaves(); i2c_check_slaves();
ch1116_main(); ch1116_main();
gui_main(); gui_main();
gui_set_wifi_connecting();
gui_set_server_connecting();
// display_print8_str(0, 0, "Ambient Light"); // display_print8_str(0, 0, "Ambient Light");
ci_03t_init(); // ci_03t_init();
// apds_9960_init(); // apds_9960_init();
// apds_9960_auto_fetch(); // apds_9960_auto_fetch();
// auto_fetch_temperature(); // auto_fetch_temperature();
@ -39,14 +43,17 @@ void app_main(void) {
// ui_input_init(); // ui_input_init();
// xTaskCreate(mqtt_publish_ui_input, "mqtt_publish_ui_input", 2048, NULL, 10, // xTaskCreate(mqtt_publish_ui_input, "mqtt_publish_ui_input", 2048, NULL, 10,
// NULL); // NULL);
vTaskDelay(pdMS_TO_TICKS(10)); // vTaskDelay(pdMS_TO_TICKS(10));
light_play(light_mode_connection_wifi); light_play(light_mode_connection_wifi);
if (connect_wifi()) { if (connect_wifi()) {
gui_set_wifi_connected();
light_play(light_mode_idle); light_play(light_mode_idle);
} else {
gui_set_wifi_disconnected();
} }
udp_server_init(); udp_server_init();
service_discovery_init(); // service_discovery_init();
vTaskDelay(pdMS_TO_TICKS(1000)); // vTaskDelay(pdMS_TO_TICKS(1000));
// mqtt_app_start(); // mqtt_app_start();
// if (waiting_for_mqtt_connected()) { // if (waiting_for_mqtt_connected()) {
// light_play(light_mode_mqtt_connected); // light_play(light_mode_mqtt_connected);

View File

@ -151,14 +151,7 @@ bool wifi_init_sta(void) {
} }
bool connect_wifi(void) { bool connect_wifi(void) {
// Initialize NVS //! Should init NVS before wifi init
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_LOGI(WIFI_TAG, "ESP_WIFI_MODE_STA"); ESP_LOGI(WIFI_TAG, "ESP_WIFI_MODE_STA");
return wifi_init_sta(); return wifi_init_sta();