firmware: Attempt at working LVGL on LCD
This commit is contained in:
		
							
								
								
									
										2
									
								
								firmware/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								firmware/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,5 @@
 | 
				
			|||||||
/build/
 | 
					/build/
 | 
				
			||||||
 | 
					/managed_components/
 | 
				
			||||||
sdkconfig
 | 
					sdkconfig
 | 
				
			||||||
sdkconfig.old
 | 
					sdkconfig.old
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								firmware/dependencies.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								firmware/dependencies.lock
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					dependencies:
 | 
				
			||||||
 | 
					  idf:
 | 
				
			||||||
 | 
					    source:
 | 
				
			||||||
 | 
					      type: idf
 | 
				
			||||||
 | 
					    version: 5.3.1
 | 
				
			||||||
 | 
					  lvgl/lvgl:
 | 
				
			||||||
 | 
					    component_hash: 096c69af22eaf8a2b721e3913da91918c5e6bf1a762a113ec01f401aa61337a0
 | 
				
			||||||
 | 
					    dependencies: []
 | 
				
			||||||
 | 
					    source:
 | 
				
			||||||
 | 
					      registry_url: https://components.espressif.com/
 | 
				
			||||||
 | 
					      type: service
 | 
				
			||||||
 | 
					    version: 9.2.2
 | 
				
			||||||
 | 
					direct_dependencies:
 | 
				
			||||||
 | 
					- idf
 | 
				
			||||||
 | 
					- lvgl/lvgl
 | 
				
			||||||
 | 
					manifest_hash: 5572feed6f42d829a5cb8a4d05d14bdccf26a3eea1ab283866a22e031aea011b
 | 
				
			||||||
 | 
					target: esp32s3
 | 
				
			||||||
 | 
					version: 2.0.0
 | 
				
			||||||
@@ -1,2 +1,3 @@
 | 
				
			|||||||
idf_component_register(SRCS "valconomy.c"
 | 
					idf_component_register(
 | 
				
			||||||
 | 
					  SRCS "valconomy.c" "lvgl_demo_ui.c"
 | 
				
			||||||
  INCLUDE_DIRS ".")
 | 
					  INCLUDE_DIRS ".")
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								firmware/main/idf_component.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								firmware/main/idf_component.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					## IDF Component Manager Manifest File
 | 
				
			||||||
 | 
					dependencies:
 | 
				
			||||||
 | 
					  lvgl/lvgl: "^9.2.2"
 | 
				
			||||||
 | 
					  ## Required IDF version
 | 
				
			||||||
 | 
					  idf:
 | 
				
			||||||
 | 
					    version: ">=4.1.0"
 | 
				
			||||||
 | 
					  # # Put list of dependencies here
 | 
				
			||||||
 | 
					  # # For components maintained by Espressif:
 | 
				
			||||||
 | 
					  # component: "~1.0.0"
 | 
				
			||||||
 | 
					  # # For 3rd party components:
 | 
				
			||||||
 | 
					  # username/component: ">=1.0.0,<2.0.0"
 | 
				
			||||||
 | 
					  # username2/component2:
 | 
				
			||||||
 | 
					  #   version: "~1.0.0"
 | 
				
			||||||
 | 
					  #   # For transient dependencies `public` flag can be set.
 | 
				
			||||||
 | 
					  #   # `public` flag doesn't have an effect dependencies of the `main` component.
 | 
				
			||||||
 | 
					  #   # All dependencies of `main` are public by default.
 | 
				
			||||||
 | 
					  #   public: true
 | 
				
			||||||
							
								
								
									
										150
									
								
								firmware/main/lvgl_demo_ui.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								firmware/main/lvgl_demo_ui.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					#include "lvgl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static lv_style_t style_bullet;
 | 
				
			||||||
 | 
					static lv_obj_t *scale1;
 | 
				
			||||||
 | 
					static const lv_font_t *font_normal = &lv_font_montserrat_14;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static lv_obj_t *create_scale_box(lv_obj_t *parent, const char *text1, const char *text2, const char *text3)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lv_obj_t *scale = lv_scale_create(parent);
 | 
				
			||||||
 | 
					    lv_obj_center(scale);
 | 
				
			||||||
 | 
					    lv_obj_set_size(scale, 300, 300);
 | 
				
			||||||
 | 
					    lv_scale_set_mode(scale, LV_SCALE_MODE_ROUND_OUTER);
 | 
				
			||||||
 | 
					    lv_scale_set_label_show(scale, false);
 | 
				
			||||||
 | 
					    lv_scale_set_post_draw(scale, true);
 | 
				
			||||||
 | 
					    lv_obj_set_width(scale, LV_PCT(100));
 | 
				
			||||||
 | 
					    lv_obj_set_style_pad_all(scale, 30, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_obj_t *bullet1 = lv_obj_create(parent);
 | 
				
			||||||
 | 
					    lv_obj_set_size(bullet1, 13, 13);
 | 
				
			||||||
 | 
					    lv_obj_remove_style(bullet1, NULL, LV_PART_SCROLLBAR);
 | 
				
			||||||
 | 
					    lv_obj_add_style(bullet1, &style_bullet, 0);
 | 
				
			||||||
 | 
					    lv_obj_set_style_bg_color(bullet1, lv_palette_main(LV_PALETTE_RED), 0);
 | 
				
			||||||
 | 
					    lv_obj_t *label1 = lv_label_create(parent);
 | 
				
			||||||
 | 
					    lv_label_set_text(label1, text1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_obj_t *bullet2 = lv_obj_create(parent);
 | 
				
			||||||
 | 
					    lv_obj_set_size(bullet2, 13, 13);
 | 
				
			||||||
 | 
					    lv_obj_remove_style(bullet2, NULL, LV_PART_SCROLLBAR);
 | 
				
			||||||
 | 
					    lv_obj_add_style(bullet2, &style_bullet, 0);
 | 
				
			||||||
 | 
					    lv_obj_set_style_bg_color(bullet2, lv_palette_main(LV_PALETTE_BLUE), 0);
 | 
				
			||||||
 | 
					    lv_obj_t *label2 = lv_label_create(parent);
 | 
				
			||||||
 | 
					    lv_label_set_text(label2, text2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_obj_t *bullet3 = lv_obj_create(parent);
 | 
				
			||||||
 | 
					    lv_obj_set_size(bullet3, 13, 13);
 | 
				
			||||||
 | 
					    lv_obj_remove_style(bullet3,  NULL, LV_PART_SCROLLBAR);
 | 
				
			||||||
 | 
					    lv_obj_add_style(bullet3, &style_bullet, 0);
 | 
				
			||||||
 | 
					    lv_obj_set_style_bg_color(bullet3, lv_palette_main(LV_PALETTE_GREEN), 0);
 | 
				
			||||||
 | 
					    lv_obj_t *label3 = lv_label_create(parent);
 | 
				
			||||||
 | 
					    lv_label_set_text(label3, text3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static int32_t grid_col_dsc[] = {LV_GRID_CONTENT, LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
 | 
				
			||||||
 | 
					    static int32_t grid_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
 | 
				
			||||||
 | 
					    lv_obj_set_grid_dsc_array(parent, grid_col_dsc, grid_row_dsc);
 | 
				
			||||||
 | 
					    lv_obj_set_grid_cell(scale, LV_GRID_ALIGN_START, 0, 2, LV_GRID_ALIGN_START, 1, 1);
 | 
				
			||||||
 | 
					    lv_obj_set_grid_cell(bullet1, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_START, 2, 1);
 | 
				
			||||||
 | 
					    lv_obj_set_grid_cell(bullet2, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_START, 3, 1);
 | 
				
			||||||
 | 
					    lv_obj_set_grid_cell(bullet3, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_START, 4, 1);
 | 
				
			||||||
 | 
					    lv_obj_set_grid_cell(label1, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_START, 2, 1);
 | 
				
			||||||
 | 
					    lv_obj_set_grid_cell(label2, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_START, 3, 1);
 | 
				
			||||||
 | 
					    lv_obj_set_grid_cell(label3, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_START, 4, 1);
 | 
				
			||||||
 | 
					    return scale;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void scale1_indic1_anim_cb(void *var, int32_t v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lv_arc_set_value(var, v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_obj_t *card = lv_obj_get_parent(scale1);
 | 
				
			||||||
 | 
					    lv_obj_t *label = lv_obj_get_child(card, -5);
 | 
				
			||||||
 | 
					    lv_label_set_text_fmt(label, "Revenue: %"LV_PRId32" %%", v);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void scale1_indic2_anim_cb(void *var, int32_t v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lv_arc_set_value(var, v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_obj_t *card = lv_obj_get_parent(scale1);
 | 
				
			||||||
 | 
					    lv_obj_t *label = lv_obj_get_child(card, -3);
 | 
				
			||||||
 | 
					    lv_label_set_text_fmt(label, "Sales: %"LV_PRId32" %%", v);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void scale1_indic3_anim_cb(void *var, int32_t v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lv_arc_set_value(var, v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_obj_t *card = lv_obj_get_parent(scale1);
 | 
				
			||||||
 | 
					    lv_obj_t *label = lv_obj_get_child(card, -1);
 | 
				
			||||||
 | 
					    lv_label_set_text_fmt(label, "Costs: %"LV_PRId32" %%", v);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void example_lvgl_demo_ui(lv_display_t *disp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // init default theme
 | 
				
			||||||
 | 
					    lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), LV_THEME_DEFAULT_DARK,
 | 
				
			||||||
 | 
					                          font_normal);
 | 
				
			||||||
 | 
					    // bullet style
 | 
				
			||||||
 | 
					    lv_style_init(&style_bullet);
 | 
				
			||||||
 | 
					    lv_style_set_border_width(&style_bullet, 0);
 | 
				
			||||||
 | 
					    lv_style_set_radius(&style_bullet, LV_RADIUS_CIRCLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_obj_t *parent = lv_display_get_screen_active(disp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // create scale widget
 | 
				
			||||||
 | 
					    scale1 = create_scale_box(parent, "Revenue", "Sales", "Costs");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // create arc indicators
 | 
				
			||||||
 | 
					    lv_obj_t *arc;
 | 
				
			||||||
 | 
					    arc = lv_arc_create(scale1);
 | 
				
			||||||
 | 
					    lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
 | 
				
			||||||
 | 
					    lv_obj_remove_style(arc, NULL, LV_PART_MAIN);
 | 
				
			||||||
 | 
					    lv_obj_set_size(arc, lv_pct(100), lv_pct(100));
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_opa(arc, 0, 0);
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_width(arc, 15, LV_PART_INDICATOR);
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_color(arc, lv_palette_main(LV_PALETTE_BLUE), LV_PART_INDICATOR);
 | 
				
			||||||
 | 
					    lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // animation
 | 
				
			||||||
 | 
					    lv_anim_t a;
 | 
				
			||||||
 | 
					    lv_anim_init(&a);
 | 
				
			||||||
 | 
					    lv_anim_set_values(&a, 20, 100);
 | 
				
			||||||
 | 
					    lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
 | 
				
			||||||
 | 
					    lv_anim_set_exec_cb(&a, scale1_indic1_anim_cb);
 | 
				
			||||||
 | 
					    lv_anim_set_var(&a, arc);
 | 
				
			||||||
 | 
					    lv_anim_set_duration(&a, 4100);
 | 
				
			||||||
 | 
					    lv_anim_set_playback_duration(&a, 2700);
 | 
				
			||||||
 | 
					    lv_anim_start(&a);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arc = lv_arc_create(scale1);
 | 
				
			||||||
 | 
					    lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
 | 
				
			||||||
 | 
					    lv_obj_set_size(arc, lv_pct(100), lv_pct(100));
 | 
				
			||||||
 | 
					    lv_obj_set_style_margin_all(arc, 20, 0);
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_opa(arc, 0, 0);
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_width(arc, 15, LV_PART_INDICATOR);
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_color(arc, lv_palette_main(LV_PALETTE_RED), LV_PART_INDICATOR);
 | 
				
			||||||
 | 
					    lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
 | 
				
			||||||
 | 
					    lv_obj_center(arc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_anim_set_exec_cb(&a, scale1_indic2_anim_cb);
 | 
				
			||||||
 | 
					    lv_anim_set_var(&a, arc);
 | 
				
			||||||
 | 
					    lv_anim_set_duration(&a, 2600);
 | 
				
			||||||
 | 
					    lv_anim_set_playback_duration(&a, 3200);
 | 
				
			||||||
 | 
					    lv_anim_start(&a);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arc = lv_arc_create(scale1);
 | 
				
			||||||
 | 
					    lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
 | 
				
			||||||
 | 
					    lv_obj_set_size(arc, lv_pct(100), lv_pct(100));
 | 
				
			||||||
 | 
					    lv_obj_set_style_margin_all(arc, 40, 0);
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_opa(arc, 0, 0);
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_width(arc, 15, LV_PART_INDICATOR);
 | 
				
			||||||
 | 
					    lv_obj_set_style_arc_color(arc, lv_palette_main(LV_PALETTE_GREEN), LV_PART_INDICATOR);
 | 
				
			||||||
 | 
					    lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
 | 
				
			||||||
 | 
					    lv_obj_center(arc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lv_anim_set_exec_cb(&a, scale1_indic3_anim_cb);
 | 
				
			||||||
 | 
					    lv_anim_set_var(&a, arc);
 | 
				
			||||||
 | 
					    lv_anim_set_duration(&a, 2800);
 | 
				
			||||||
 | 
					    lv_anim_set_playback_duration(&a, 1800);
 | 
				
			||||||
 | 
					    lv_anim_start(&a);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,46 +1,214 @@
 | 
				
			|||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <sys/lock.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "sdkconfig.h"
 | 
					#include "sdkconfig.h"
 | 
				
			||||||
#include "freertos/FreeRTOS.h"
 | 
					#include "freertos/FreeRTOS.h"
 | 
				
			||||||
#include "freertos/task.h"
 | 
					#include "freertos/task.h"
 | 
				
			||||||
#include "esp_chip_info.h"
 | 
					
 | 
				
			||||||
#include "esp_flash.h"
 | 
					#include "esp_err.h"
 | 
				
			||||||
#include "esp_system.h"
 | 
					#include "esp_log.h"
 | 
				
			||||||
 | 
					#include "esp_timer.h"
 | 
				
			||||||
 | 
					#include "esp_lcd_panel_ops.h"
 | 
				
			||||||
 | 
					#include "esp_lcd_panel_rgb.h"
 | 
				
			||||||
 | 
					#include "driver/i2c_master.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lvgl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LCD_HRES        800
 | 
				
			||||||
 | 
					#define LCD_VRES        480
 | 
				
			||||||
 | 
					#define LCD_PIXEL_SIZE    2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// in ms
 | 
				
			||||||
 | 
					#define LVGL_TICK_PERIOD     2
 | 
				
			||||||
 | 
					#define LVGL_TASK_PRIORITY   2
 | 
				
			||||||
 | 
					#define LVGL_TASK_STACK_SIZE (4 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *TAG = "valconomy";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i2c_master_bus_handle_t i2c_bus_handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LVGL library is not thread-safe, this example will call LVGL APIs from different tasks, so use a mutex to protect it
 | 
				
			||||||
 | 
					static _lock_t lvgl_api_lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void example_lvgl_demo_ui(lv_display_t *disp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool example_on_vsync(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_ctx) {
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
 | 
				
			||||||
 | 
					  esp_lcd_panel_handle_t panel_handle = lv_display_get_user_data(disp);
 | 
				
			||||||
 | 
					  // pass the draw buffer to the driver
 | 
				
			||||||
 | 
					  esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map);
 | 
				
			||||||
 | 
					  lv_disp_flush_ready(disp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void example_increase_lvgl_tick(void *arg) {
 | 
				
			||||||
 | 
					  /* Tell LVGL how many milliseconds has elapsed */
 | 
				
			||||||
 | 
					  lv_tick_inc(LVGL_TICK_PERIOD);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void example_lvgl_port_task(void *arg) {
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Starting LVGL task");
 | 
				
			||||||
 | 
					  uint32_t time_till_next_ms = 0;
 | 
				
			||||||
 | 
					  while (1) {
 | 
				
			||||||
 | 
					    _lock_acquire(&lvgl_api_lock);
 | 
				
			||||||
 | 
					    time_till_next_ms = lv_timer_handler();
 | 
				
			||||||
 | 
					    _lock_release(&lvgl_api_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // in case of task watch dog timeout, set the minimal delay to 10ms
 | 
				
			||||||
 | 
					    if (time_till_next_ms < 10) {
 | 
				
			||||||
 | 
					       time_till_next_ms = 10;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     usleep(1000 * time_till_next_ms);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static esp_err_t i2c_master_init(void) {
 | 
				
			||||||
 | 
					  i2c_master_bus_config_t i2c_mst_config = {
 | 
				
			||||||
 | 
					    .clk_source = I2C_CLK_SRC_DEFAULT,
 | 
				
			||||||
 | 
					    .i2c_port = I2C_NUM_0,
 | 
				
			||||||
 | 
					    .scl_io_num = 9,
 | 
				
			||||||
 | 
					    .sda_io_num = 8,
 | 
				
			||||||
 | 
					    .glitch_ignore_cnt = 7,
 | 
				
			||||||
 | 
					    .flags.enable_internal_pullup = true,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return i2c_new_master_bus(&i2c_mst_config, &i2c_bus_handle);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void setup_lcd() {
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Init I2C");
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(i2c_master_init());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  i2c_device_config_t exio_dev_cfg = {
 | 
				
			||||||
 | 
					    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
 | 
				
			||||||
 | 
					    .device_address = 0x24, // CH422G config register
 | 
				
			||||||
 | 
					    .scl_speed_hz = 100000,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  i2c_master_dev_handle_t exio_cfg_handle, exio_o_handle;
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_handle, &exio_dev_cfg, &exio_cfg_handle));
 | 
				
			||||||
 | 
					  exio_dev_cfg.device_address = 0x38;
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_handle, &exio_dev_cfg, &exio_o_handle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t i2c_b;
 | 
				
			||||||
 | 
					  i2c_b = 0x01; // Output enable
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(i2c_master_transmit(exio_cfg_handle, &i2c_b, 1, -1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  i2c_b = 0x00; // Reset everything
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(i2c_master_transmit(exio_o_handle, &i2c_b, 1, -1));
 | 
				
			||||||
 | 
					  usleep(10 * 1000);
 | 
				
			||||||
 | 
					  i2c_b = 0x08; // Pull LCD out of reset
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(i2c_master_transmit(exio_o_handle, &i2c_b, 1, -1));
 | 
				
			||||||
 | 
					  usleep(100 * 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Install RGB LCD panel driver");
 | 
				
			||||||
 | 
					  esp_lcd_panel_handle_t panel_handle = NULL;
 | 
				
			||||||
 | 
					  esp_lcd_rgb_panel_config_t panel_config = {
 | 
				
			||||||
 | 
					    .data_width = 16, // RGB565
 | 
				
			||||||
 | 
					    .psram_trans_align = 64,
 | 
				
			||||||
 | 
					    .num_fbs = 2,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .clk_src = LCD_CLK_SRC_DEFAULT,
 | 
				
			||||||
 | 
					    .disp_gpio_num = -1, // Only accessible via GPIO expander
 | 
				
			||||||
 | 
					    .pclk_gpio_num = 7,
 | 
				
			||||||
 | 
					    .vsync_gpio_num = 3,
 | 
				
			||||||
 | 
					    .hsync_gpio_num = 46,
 | 
				
			||||||
 | 
					    .de_gpio_num = 5,
 | 
				
			||||||
 | 
					    .data_gpio_nums = {
 | 
				
			||||||
 | 
					      14, // B3
 | 
				
			||||||
 | 
					      38, // B4
 | 
				
			||||||
 | 
					      18, // B5
 | 
				
			||||||
 | 
					      17, // B6
 | 
				
			||||||
 | 
					      10, // B7
 | 
				
			||||||
 | 
					      39, // G2
 | 
				
			||||||
 | 
					       0, // G3
 | 
				
			||||||
 | 
					      45, // G4
 | 
				
			||||||
 | 
					      48, // G5
 | 
				
			||||||
 | 
					      47, // G6
 | 
				
			||||||
 | 
					      21, // G7
 | 
				
			||||||
 | 
					       1, // R3
 | 
				
			||||||
 | 
					       2, // R4
 | 
				
			||||||
 | 
					      42, // R5
 | 
				
			||||||
 | 
					      41, // R6
 | 
				
			||||||
 | 
					      40, // R7
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    .timings = {
 | 
				
			||||||
 | 
					      .pclk_hz = 18 * 1000 * 1000, // 18000000 / (hs+hbp+hfp+hres) / (vs+vbp+hfp+vres) = ~42Hz
 | 
				
			||||||
 | 
					      .h_res = LCD_HRES,
 | 
				
			||||||
 | 
					      .v_res = LCD_VRES,
 | 
				
			||||||
 | 
					      .hsync_back_porch = 8,
 | 
				
			||||||
 | 
					      .hsync_front_porch = 8,
 | 
				
			||||||
 | 
					      .hsync_pulse_width = 4,
 | 
				
			||||||
 | 
					      .vsync_back_porch = 16,
 | 
				
			||||||
 | 
					      .vsync_front_porch = 16,
 | 
				
			||||||
 | 
					      .vsync_pulse_width = 4,
 | 
				
			||||||
 | 
					      .flags = {
 | 
				
			||||||
 | 
					        .pclk_active_neg = true,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    .flags.fb_in_psram = true, // allocate frame buffer in PSRAM
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Initialize RGB LCD panel");
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Turn on LCD backlight");
 | 
				
			||||||
 | 
					  i2c_b = 0x0e; // LCD out of reset, backlight on
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(i2c_master_transmit(exio_o_handle, &i2c_b, 1, -1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Initialize LVGL library");
 | 
				
			||||||
 | 
					  lv_init();
 | 
				
			||||||
 | 
					  // create a lvgl display
 | 
				
			||||||
 | 
					  lv_display_t *display = lv_display_create(LCD_HRES, LCD_VRES);
 | 
				
			||||||
 | 
					  // associate the rgb panel handle to the display
 | 
				
			||||||
 | 
					  lv_display_set_user_data(display, panel_handle);
 | 
				
			||||||
 | 
					  // set color depth
 | 
				
			||||||
 | 
					  lv_display_set_color_format(display, LV_COLOR_FORMAT_RGB565);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // create draw buffers
 | 
				
			||||||
 | 
					  void *buf1 = NULL;
 | 
				
			||||||
 | 
					  void *buf2 = NULL;
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Use frame buffers as LVGL draw buffers");
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(esp_lcd_rgb_panel_get_frame_buffer(panel_handle, 2, &buf1, &buf2));
 | 
				
			||||||
 | 
					  // set LVGL draw buffers and direct mode
 | 
				
			||||||
 | 
					  lv_display_set_buffers(display, buf1, buf2, LCD_HRES * LCD_VRES * LCD_PIXEL_SIZE, LV_DISPLAY_RENDER_MODE_DIRECT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set the callback which can copy the rendered image to an area of the display
 | 
				
			||||||
 | 
					  lv_display_set_flush_cb(display, example_lvgl_flush_cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Register event callbacks");
 | 
				
			||||||
 | 
					  esp_lcd_rgb_panel_event_callbacks_t cbs = {
 | 
				
			||||||
 | 
					    .on_vsync = example_on_vsync,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, display));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Install LVGL tick timer");
 | 
				
			||||||
 | 
					  // Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
 | 
				
			||||||
 | 
					  const esp_timer_create_args_t lvgl_tick_timer_args = {
 | 
				
			||||||
 | 
					    .callback = &example_increase_lvgl_tick,
 | 
				
			||||||
 | 
					    .name = "lvgl_tick"
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  esp_timer_handle_t lvgl_tick_timer = NULL;
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
 | 
				
			||||||
 | 
					  ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, LVGL_TICK_PERIOD * 1000));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Create LVGL task");
 | 
				
			||||||
 | 
					  xTaskCreate(example_lvgl_port_task, "LVGL", LVGL_TASK_STACK_SIZE, NULL, LVGL_TASK_PRIORITY, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGI(TAG, "Display LVGL UI");
 | 
				
			||||||
 | 
					  // Lock the mutex due to the LVGL APIs are not thread-safe
 | 
				
			||||||
 | 
					  _lock_acquire(&lvgl_api_lock);
 | 
				
			||||||
 | 
					  example_lvgl_demo_ui(display);
 | 
				
			||||||
 | 
					  _lock_release(&lvgl_api_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void app_main(void) {
 | 
					void app_main(void) {
 | 
				
			||||||
  printf("Hello world!\n");
 | 
					  setup_lcd();
 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Print chip information */
 | 
					 | 
				
			||||||
  esp_chip_info_t chip_info;
 | 
					 | 
				
			||||||
  uint32_t flash_size;
 | 
					 | 
				
			||||||
  esp_chip_info(&chip_info);
 | 
					 | 
				
			||||||
  printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",
 | 
					 | 
				
			||||||
         CONFIG_IDF_TARGET,
 | 
					 | 
				
			||||||
         chip_info.cores,
 | 
					 | 
				
			||||||
         (chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",
 | 
					 | 
				
			||||||
         (chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",
 | 
					 | 
				
			||||||
         (chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",
 | 
					 | 
				
			||||||
         (chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  unsigned major_rev = chip_info.revision / 100;
 | 
					 | 
				
			||||||
  unsigned minor_rev = chip_info.revision % 100;
 | 
					 | 
				
			||||||
  printf("silicon revision v%d.%d, ", major_rev, minor_rev);
 | 
					 | 
				
			||||||
  if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
 | 
					 | 
				
			||||||
    printf("Get flash size failed");
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
 | 
					 | 
				
			||||||
         (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (int i = 10; i >= 0; i--) {
 | 
					 | 
				
			||||||
    printf("Restarting in %d seconds...\n", i);
 | 
					 | 
				
			||||||
    vTaskDelay(1000 / portTICK_PERIOD_MS);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  printf("Restarting now.\n");
 | 
					 | 
				
			||||||
  fflush(stdout);
 | 
					 | 
				
			||||||
  esp_restart();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,18 @@
 | 
				
			|||||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
 | 
					# This file was generated using idf.py save-defconfig. It can be edited manually.
 | 
				
			||||||
# Espressif IoT Development Framework (ESP-IDF) 5.3.1 Project Minimal Configuration
 | 
					# Espressif IoT Development Framework (ESP-IDF) 5.3.1 Project Minimal Configuration
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					CONFIG_IDF_TARGET="esp32s3"
 | 
				
			||||||
 | 
					CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=n
 | 
				
			||||||
 | 
					CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
 | 
				
			||||||
 | 
					CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
 | 
				
			||||||
 | 
					CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
 | 
				
			||||||
 | 
					CONFIG_SPIRAM=y
 | 
				
			||||||
 | 
					CONFIG_SPIRAM_MODE_OCT=y
 | 
				
			||||||
 | 
					CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
 | 
				
			||||||
 | 
					CONFIG_SPIRAM_RODATA=y
 | 
				
			||||||
 | 
					CONFIG_SPIRAM_SPEED_120M=y
 | 
				
			||||||
 | 
					CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
 | 
				
			||||||
 | 
					CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
 | 
				
			||||||
CONFIG_ESP_WIFI_DPP_SUPPORT=y
 | 
					CONFIG_ESP_WIFI_DPP_SUPPORT=y
 | 
				
			||||||
 | 
					CONFIG_FREERTOS_HZ=1000
 | 
				
			||||||
 | 
					CONFIG_IDF_EXPERIMENTAL_FEATURES=y
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user