diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f6f7042..3b1e6b6 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,13 +1,27 @@ -idf_component_register(SRCS - "main.c" - "lvgl_demo_ui.c" - "ui.c" - "ui_helpers.c" - "screens/ui_Screen1.c" - "components/ui_comp_hook.c" - PRIV_REQUIRES - esp_wifi - nvs_flash +idf_component_register(SRCS + "app/app_main.c" + "app/ui_handlers.c" + "bsp/display.c" + "bsp/touch.c" + "bsp/lvgl_port.c" + "services/wifi_manager.c" + "ui/ui.c" + "ui/ui_helpers.c" + "ui/screens/ui_Screen1.c" + "ui/widgets/ui_comp_hook.c" + PRIV_REQUIRES + esp_wifi + esp_netif + nvs_flash esp_driver_ledc + esp_driver_spi + esp_driver_gpio + esp_driver_i2c + esp_lcd + esp_timer lvgl - INCLUDE_DIRS ".") + INCLUDE_DIRS + "app" + "bsp" + "services" + "ui") diff --git a/main/app/app_main.c b/main/app/app_main.c new file mode 100644 index 0000000..fa78053 --- /dev/null +++ b/main/app/app_main.c @@ -0,0 +1,40 @@ +#include "esp_log.h" +#include "nvs_flash.h" + +#include "board_config.h" +#include "display.h" +#include "lvgl_port.h" +#include "touch.h" +#include "ui.h" +#include "wifi_manager.h" + +static const char *TAG = "app"; + +void app_main(void) +{ + esp_log_level_set("*", ESP_LOG_INFO); + + 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_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + ESP_ERROR_CHECK(display_init(&io_handle, &panel_handle)); + + lv_display_t *display = lvgl_port_init(io_handle, panel_handle); + +#if BOARD_TOUCH_ENABLED + ESP_ERROR_CHECK(touch_init(display)); +#endif + + lvgl_port_lock(); + ui_init(); + lvgl_port_unlock(); + + ESP_LOGI(TAG, "Starting WiFi"); + wifi_manager_init(); +} diff --git a/main/app/ui_handlers.c b/main/app/ui_handlers.c new file mode 100644 index 0000000..7fae882 --- /dev/null +++ b/main/app/ui_handlers.c @@ -0,0 +1,4 @@ +#include "ui_handlers.h" +#include "ui_events.h" + +/* Add callback implementations here when SquareLine Studio generates events. */ diff --git a/main/app/ui_handlers.h b/main/app/ui_handlers.h new file mode 100644 index 0000000..74423bd --- /dev/null +++ b/main/app/ui_handlers.h @@ -0,0 +1,3 @@ +#pragma once + +/* UI event callbacks declared in ui_events.h are implemented in ui_handlers.c */ diff --git a/main/bsp/board_config.h b/main/bsp/board_config.h new file mode 100644 index 0000000..c3b79c4 --- /dev/null +++ b/main/bsp/board_config.h @@ -0,0 +1,50 @@ +#pragma once + +#include "driver/i2c.h" +#include "driver/ledc.h" +#include "driver/spi_master.h" + +/* LCD SPI (ST7789) */ +#define BOARD_LCD_HOST SPI2_HOST +#define BOARD_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) +#define BOARD_LCD_H_RES 240 +#define BOARD_LCD_V_RES 320 +#define BOARD_LCD_CMD_BITS 8 +#define BOARD_LCD_PARAM_BITS 8 + +#define BOARD_PIN_LCD_SCLK 10 +#define BOARD_PIN_LCD_MOSI 13 +#define BOARD_PIN_LCD_MISO (-1) +#define BOARD_PIN_LCD_DC 11 +#define BOARD_PIN_LCD_RST 9 +#define BOARD_PIN_LCD_CS 12 +#define BOARD_PIN_BK_LIGHT 14 + +/* Backlight PWM */ +#define BOARD_LCD_BK_LIGHT_CH LEDC_CHANNEL_0 +#define BOARD_LCD_BK_LIGHT_TIMER LEDC_TIMER_0 +#define BOARD_LCD_BK_LIGHT_FREQ 5000 +#define BOARD_LCD_BK_LIGHT_ON_LEVEL 1 +#define BOARD_LCD_BK_LIGHT_OFF_LEVEL (!BOARD_LCD_BK_LIGHT_ON_LEVEL) + +/* Touch I2C (CST816) */ +#define BOARD_PIN_TOUCH_SDA 47 +#define BOARD_PIN_TOUCH_SCL 48 +#define BOARD_PIN_TOUCH_RST 17 +#define BOARD_PIN_TOUCH_INT 21 + +#define BOARD_TOUCH_I2C_NUM I2C_NUM_0 +#define BOARD_TOUCH_I2C_FREQ_HZ 400000 +#define BOARD_TOUCH_ENABLED 0 + +/* User IO */ +#define BOARD_PIN_KEY 4 +#define BOARD_PIN_LED 16 + +/* LVGL port */ +#define BOARD_LVGL_DRAW_BUF_LINES 20 +#define BOARD_LVGL_TICK_PERIOD_MS 2 +#define BOARD_LVGL_TASK_MAX_DELAY_MS 500 +#define BOARD_LVGL_TASK_MIN_DELAY_MS (1000 / CONFIG_FREERTOS_HZ) +#define BOARD_LVGL_TASK_STACK_SIZE (8 * 1024) +#define BOARD_LVGL_TASK_PRIORITY 2 diff --git a/main/bsp/display.c b/main/bsp/display.c new file mode 100644 index 0000000..85387e1 --- /dev/null +++ b/main/bsp/display.c @@ -0,0 +1,98 @@ +#include "display.h" + +#include "board_config.h" + +#include "driver/gpio.h" +#include "driver/ledc.h" +#include "driver/spi_master.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_panel_st7789.h" +#include "esp_lcd_panel_vendor.h" +#include "esp_log.h" + +static const char *TAG = "display"; + +void display_backlight_set_brightness(uint16_t brightness) +{ + if (brightness > 1023) { + brightness = 1023; + } + ESP_ERROR_CHECK( + ledc_set_duty(LEDC_LOW_SPEED_MODE, BOARD_LCD_BK_LIGHT_CH, brightness)); + ESP_ERROR_CHECK( + ledc_update_duty(LEDC_LOW_SPEED_MODE, BOARD_LCD_BK_LIGHT_CH)); +} + +void display_backlight_on(void) +{ + display_backlight_set_brightness(1023); +} + +esp_err_t display_init(esp_lcd_panel_io_handle_t *io_handle_out, + esp_lcd_panel_handle_t *panel_handle_out) +{ + ESP_LOGI(TAG, "Configure LCD backlight PWM"); + ledc_timer_config_t ledc_timer = { + .speed_mode = LEDC_LOW_SPEED_MODE, + .timer_num = BOARD_LCD_BK_LIGHT_TIMER, + .duty_resolution = LEDC_TIMER_10_BIT, + .freq_hz = BOARD_LCD_BK_LIGHT_FREQ, + .clk_cfg = LEDC_AUTO_CLK, + }; + ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); + + ledc_channel_config_t ledc_channel = { + .speed_mode = LEDC_LOW_SPEED_MODE, + .channel = BOARD_LCD_BK_LIGHT_CH, + .timer_sel = BOARD_LCD_BK_LIGHT_TIMER, + .intr_type = LEDC_INTR_DISABLE, + .gpio_num = BOARD_PIN_BK_LIGHT, + .duty = 0, + .hpoint = 0, + }; + ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); + + ESP_LOGI(TAG, "Initialize SPI bus"); + spi_bus_config_t buscfg = { + .sclk_io_num = BOARD_PIN_LCD_SCLK, + .mosi_io_num = BOARD_PIN_LCD_MOSI, + .miso_io_num = BOARD_PIN_LCD_MISO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = BOARD_LCD_H_RES * 80 * sizeof(uint16_t), + }; + ESP_ERROR_CHECK(spi_bus_initialize(BOARD_LCD_HOST, &buscfg, SPI_DMA_CH_AUTO)); + + ESP_LOGI(TAG, "Install panel IO"); + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_io_spi_config_t io_config = { + .dc_gpio_num = BOARD_PIN_LCD_DC, + .cs_gpio_num = BOARD_PIN_LCD_CS, + .pclk_hz = BOARD_LCD_PIXEL_CLOCK_HZ, + .lcd_cmd_bits = BOARD_LCD_CMD_BITS, + .lcd_param_bits = BOARD_LCD_PARAM_BITS, + .spi_mode = 0, + .trans_queue_depth = 10, + }; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(BOARD_LCD_HOST, &io_config, &io_handle)); + + esp_lcd_panel_handle_t panel_handle = NULL; + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = BOARD_PIN_LCD_RST, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR, + .bits_per_pixel = 16, + }; + ESP_LOGI(TAG, "Install ST7789 panel driver"); + ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, false)); + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); + + ESP_LOGI(TAG, "Turn on LCD backlight"); + gpio_set_level(BOARD_PIN_BK_LIGHT, BOARD_LCD_BK_LIGHT_ON_LEVEL); + + *io_handle_out = io_handle; + *panel_handle_out = panel_handle; + return ESP_OK; +} diff --git a/main/bsp/display.h b/main/bsp/display.h new file mode 100644 index 0000000..2afc18b --- /dev/null +++ b/main/bsp/display.h @@ -0,0 +1,10 @@ +#pragma once + +#include "esp_err.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_ops.h" + +esp_err_t display_init(esp_lcd_panel_io_handle_t *io_handle_out, + esp_lcd_panel_handle_t *panel_handle_out); +void display_backlight_set_brightness(uint16_t brightness); +void display_backlight_on(void); diff --git a/main/bsp/lvgl_port.c b/main/bsp/lvgl_port.c new file mode 100644 index 0000000..291a350 --- /dev/null +++ b/main/bsp/lvgl_port.c @@ -0,0 +1,119 @@ +#include "lvgl_port.h" + +#include "board_config.h" + +#include "driver/spi_master.h" +#include "esp_lcd_panel_ops.h" +#include "esp_log.h" +#include "esp_timer.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "sys/lock.h" +#include "sys/param.h" +#include "unistd.h" + +#include + +static const char *TAG = "lvgl_port"; +static _lock_t s_lvgl_api_lock; + +static bool notify_flush_ready(esp_lcd_panel_io_handle_t panel_io, + esp_lcd_panel_io_event_data_t *edata, + void *user_ctx) +{ + (void)panel_io; + (void)edata; + lv_display_t *disp = (lv_display_t *)user_ctx; + lv_display_flush_ready(disp); + return false; +} + +static void 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); + int offsetx1 = area->x1; + int offsetx2 = area->x2; + int offsety1 = area->y1; + int offsety2 = area->y2; + lv_draw_sw_rgb565_swap(px_map, + (offsetx2 + 1 - offsetx1) * (offsety2 + 1 - offsety1)); + esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, + offsety2 + 1, px_map); +} + +static void increase_lvgl_tick(void *arg) +{ + (void)arg; + lv_tick_inc(BOARD_LVGL_TICK_PERIOD_MS); +} + +static void lvgl_port_task(void *arg) +{ + (void)arg; + ESP_LOGI(TAG, "Starting LVGL task"); + uint32_t time_till_next_ms = 0; + while (1) { + _lock_acquire(&s_lvgl_api_lock); + time_till_next_ms = lv_timer_handler(); + _lock_release(&s_lvgl_api_lock); + time_till_next_ms = MAX(time_till_next_ms, BOARD_LVGL_TASK_MIN_DELAY_MS); + time_till_next_ms = MIN(time_till_next_ms, BOARD_LVGL_TASK_MAX_DELAY_MS); + usleep(1000 * time_till_next_ms); + } +} + +void lvgl_port_lock(void) +{ + _lock_acquire(&s_lvgl_api_lock); +} + +void lvgl_port_unlock(void) +{ + _lock_release(&s_lvgl_api_lock); +} + +lv_display_t *lvgl_port_init(esp_lcd_panel_io_handle_t io_handle, + esp_lcd_panel_handle_t panel_handle) +{ + ESP_LOGI(TAG, "Initialize LVGL library"); + lv_init(); + + lv_display_t *display = + lv_display_create(BOARD_LCD_H_RES, BOARD_LCD_V_RES); + + size_t draw_buffer_sz = BOARD_LCD_H_RES * BOARD_LVGL_DRAW_BUF_LINES * + sizeof(lv_color16_t); + void *buf1 = spi_bus_dma_memory_alloc(BOARD_LCD_HOST, draw_buffer_sz, 0); + assert(buf1); + void *buf2 = spi_bus_dma_memory_alloc(BOARD_LCD_HOST, draw_buffer_sz, 0); + assert(buf2); + + lv_display_set_buffers(display, buf1, buf2, draw_buffer_sz, + LV_DISPLAY_RENDER_MODE_PARTIAL); + lv_display_set_user_data(display, panel_handle); + lv_display_set_color_format(display, LV_COLOR_FORMAT_RGB565); + lv_display_set_flush_cb(display, flush_cb); + + ESP_LOGI(TAG, "Install LVGL tick timer"); + const esp_timer_create_args_t lvgl_tick_timer_args = { + .callback = &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, + BOARD_LVGL_TICK_PERIOD_MS * 1000)); + + ESP_LOGI(TAG, "Register flush ready callback"); + const esp_lcd_panel_io_callbacks_t cbs = { + .on_color_trans_done = notify_flush_ready, + }; + ESP_ERROR_CHECK( + esp_lcd_panel_io_register_event_callbacks(io_handle, &cbs, display)); + + ESP_LOGI(TAG, "Create LVGL task"); + xTaskCreate(lvgl_port_task, "LVGL", BOARD_LVGL_TASK_STACK_SIZE, NULL, + BOARD_LVGL_TASK_PRIORITY, NULL); + + return display; +} diff --git a/main/bsp/lvgl_port.h b/main/bsp/lvgl_port.h new file mode 100644 index 0000000..5152941 --- /dev/null +++ b/main/bsp/lvgl_port.h @@ -0,0 +1,10 @@ +#pragma once + +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_ops.h" +#include "lvgl.h" + +lv_display_t *lvgl_port_init(esp_lcd_panel_io_handle_t io_handle, + esp_lcd_panel_handle_t panel_handle); +void lvgl_port_lock(void); +void lvgl_port_unlock(void); diff --git a/main/bsp/touch.c b/main/bsp/touch.c new file mode 100644 index 0000000..022fc61 --- /dev/null +++ b/main/bsp/touch.c @@ -0,0 +1,82 @@ +#include "touch.h" + +#include "board_config.h" + +#include "driver/gpio.h" +#include "driver/i2c.h" +#include "esp_lcd_touch.h" +#include "esp_log.h" + +static const char *TAG = "touch"; + +#if BOARD_TOUCH_ENABLED + +#include "esp_lcd_touch_cst816.h" + +static void lvgl_touch_read_cb(lv_indev_t *indev, lv_indev_data_t *data) +{ + uint16_t touchpad_x[1] = {0}; + uint16_t touchpad_y[1] = {0}; + uint8_t touchpad_cnt = 0; + + esp_lcd_touch_handle_t touch_pad = lv_indev_get_user_data(indev); + esp_lcd_touch_read_data(touch_pad); + bool touchpad_pressed = esp_lcd_touch_get_coordinates( + touch_pad, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1); + + if (touchpad_pressed && touchpad_cnt > 0) { + data->point.x = touchpad_x[0]; + data->point.y = touchpad_y[0]; + data->state = LV_INDEV_STATE_PRESSED; + } else { + data->state = LV_INDEV_STATE_RELEASED; + } +} + +esp_err_t touch_init(lv_display_t *display) +{ + ESP_LOGI(TAG, "Initialize I2C for touch"); + i2c_config_t i2c_conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = BOARD_PIN_TOUCH_SDA, + .scl_io_num = BOARD_PIN_TOUCH_SCL, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = BOARD_TOUCH_I2C_FREQ_HZ, + }; + ESP_ERROR_CHECK(i2c_param_config(BOARD_TOUCH_I2C_NUM, &i2c_conf)); + ESP_ERROR_CHECK(i2c_driver_install(BOARD_TOUCH_I2C_NUM, I2C_MODE_MASTER, 0, 0, 0)); + + ESP_LOGI(TAG, "Initialize touch controller CST816"); + esp_lcd_touch_handle_t tp = NULL; + esp_lcd_touch_config_t tp_cfg = { + .x_max = BOARD_LCD_H_RES, + .y_max = BOARD_LCD_V_RES, + .rst_gpio_num = BOARD_PIN_TOUCH_RST, + .int_gpio_num = BOARD_PIN_TOUCH_INT, + .flags = { + .swap_xy = 0, + .mirror_x = 0, + .mirror_y = 0, + }, + }; + ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst816(BOARD_TOUCH_I2C_NUM, &tp_cfg, &tp)); + + lv_indev_t *indev = lv_indev_create(); + lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_display(indev, display); + lv_indev_set_user_data(indev, tp); + lv_indev_set_read_cb(indev, lvgl_touch_read_cb); + + return ESP_OK; +} + +#else + +esp_err_t touch_init(lv_display_t *display) +{ + (void)display; + return ESP_OK; +} + +#endif diff --git a/main/bsp/touch.h b/main/bsp/touch.h new file mode 100644 index 0000000..8d37d06 --- /dev/null +++ b/main/bsp/touch.h @@ -0,0 +1,6 @@ +#pragma once + +#include "esp_err.h" +#include "lvgl.h" + +esp_err_t touch_init(lv_display_t *display); diff --git a/main/lvgl_demo_ui.c b/main/lvgl_demo_ui.c deleted file mode 100644 index a47d76f..0000000 --- a/main/lvgl_demo_ui.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: CC0-1.0 - */ - -// This demo UI is adapted from LVGL official example: https://docs.lvgl.io/master/examples.html#loader-with-arc - -#include "lvgl.h" - -static lv_obj_t * btn; -static lv_display_rotation_t rotation = LV_DISP_ROTATION_0; - -static void btn_cb(lv_event_t * e) -{ - lv_display_t *disp = lv_event_get_user_data(e); - rotation++; - if (rotation > LV_DISP_ROTATION_270) { - rotation = LV_DISP_ROTATION_0; - } - lv_disp_set_rotation(disp, rotation); -} -static void set_angle(void * obj, int32_t v) -{ - lv_arc_set_value(obj, v); -} - -void example_lvgl_demo_ui(lv_display_t *disp) -{ - lv_obj_t *scr = lv_display_get_screen_active(disp); - - btn = lv_button_create(scr); - lv_obj_t * lbl = lv_label_create(btn); - lv_label_set_text_static(lbl, LV_SYMBOL_REFRESH" ROTATE"); - lv_obj_align(btn, LV_ALIGN_BOTTOM_LEFT, 30, -30); - /*Button event*/ - lv_obj_add_event_cb(btn, btn_cb, LV_EVENT_CLICKED, disp); - - /*Create an Arc*/ - lv_obj_t * arc = lv_arc_create(scr); - lv_arc_set_rotation(arc, 270); - lv_arc_set_bg_angles(arc, 0, 360); - lv_obj_remove_style(arc, NULL, LV_PART_KNOB); /*Be sure the knob is not displayed*/ - lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE); /*To not allow adjusting by click*/ - lv_obj_center(arc); - - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, arc); - lv_anim_set_exec_cb(&a, set_angle); - lv_anim_set_duration(&a, 1000); - lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); /*Just for the demo*/ - lv_anim_set_repeat_delay(&a, 500); - lv_anim_set_values(&a, 0, 100); - lv_anim_start(&a); -} diff --git a/main/main.c b/main/main.c deleted file mode 100644 index 5a5075d..0000000 --- a/main/main.c +++ /dev/null @@ -1,576 +0,0 @@ -/* WiFi station Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include "driver/gpio.h" -#include "driver/i2c.h" -#include "driver/ledc.h" -#include "driver/spi_master.h" -#include "esp_err.h" -#include "esp_event.h" -#include "esp_lcd_panel_io.h" -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_panel_st7789.h" -#include "esp_lcd_panel_vendor.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp_timer.h" -#include "esp_wifi.h" -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "freertos/task.h" -#include "lvgl.h" -#include "nvs_flash.h" -#include -#include -#include -#include -#include - -#include "lwip/err.h" -#include "lwip/sys.h" - -#include "ui.h" - -/* The examples use WiFi configuration that you can set via project - configuration menu - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID -#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD -#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY - -// 在文件顶部定义 PWM 参数 -#define EXAMPLE_LCD_BK_LIGHT_CH LEDC_CHANNEL_0 -#define EXAMPLE_LCD_BK_LIGHT_TIMER LEDC_TIMER_0 -#define EXAMPLE_LCD_BK_LIGHT_FREQ (5000) // 5KHz PWM 频率 - -#if CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HUNT_AND_PECK -#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK -#define EXAMPLE_H2E_IDENTIFIER "" -#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HASH_TO_ELEMENT -#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT -#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID -#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_BOTH -#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH -#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID -#endif -#if CONFIG_ESP_WIFI_AUTH_OPEN -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN -#elif CONFIG_ESP_WIFI_AUTH_WEP -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP -#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK -#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK -#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK -#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK -#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK -#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK -#endif - -#if CONFIG_EXAMPLE_LCD_TOUCH_CONTROLLER_STMPE610 -#include "esp_lcd_touch_stmpe610.h" -#elif CONFIG_EXAMPLE_LCD_TOUCH_CONTROLLER_XPT2046 -#include "esp_lcd_touch_xpt2046.h" -#endif - -// Using SPI2 in the example -#define LCD_HOST SPI2_HOST - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// Please update the following configuration according to your -/// LCD spec ////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) -#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1 -#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL - -// LCD SPI 管脚(根据实际开发板) -#define EXAMPLE_PIN_NUM_SCLK 10 -#define EXAMPLE_PIN_NUM_MOSI 13 -#define EXAMPLE_PIN_NUM_MISO -1 // LCD 不需要 MISO -#define EXAMPLE_PIN_NUM_LCD_DC 11 -#define EXAMPLE_PIN_NUM_LCD_RST 9 -#define EXAMPLE_PIN_NUM_LCD_CS 12 -#define EXAMPLE_PIN_NUM_BK_LIGHT 14 // 背光 PWM -#define EXAMPLE_PIN_NUM_TOUCH_CS 15 - -// 触摸屏 - 改为 I2C 接口 -#define EXAMPLE_PIN_NUM_TOUCH_SDA 47 -#define EXAMPLE_PIN_NUM_TOUCH_SCL 48 -#define EXAMPLE_PIN_NUM_TOUCH_RST 17 -#define EXAMPLE_PIN_NUM_TOUCH_INT 21 - -// 用户按键和 LED -#define EXAMPLE_PIN_NUM_KEY 4 -#define EXAMPLE_PIN_NUM_LED 16 - -#define TOUCH_I2C_MASTER_NUM I2C_NUM_0 -#define TOUCH_I2C_MASTER_FREQ_HZ 400000 - -// The pixel number in horizontal and vertical -#define EXAMPLE_LCD_H_RES 240 -#define EXAMPLE_LCD_V_RES 320 -// Bit number used to represent command and parameter -#define EXAMPLE_LCD_CMD_BITS 8 -#define EXAMPLE_LCD_PARAM_BITS 8 - -#define EXAMPLE_LVGL_DRAW_BUF_LINES \ - 20 // number of display lines in each draw buffer -#define EXAMPLE_LVGL_TICK_PERIOD_MS 2 -#define EXAMPLE_LVGL_TASK_MAX_DELAY_MS 500 -#define EXAMPLE_LVGL_TASK_MIN_DELAY_MS 1000 / CONFIG_FREERTOS_HZ -// 8KB stack size for LVGL task -#define EXAMPLE_LVGL_TASK_STACK_SIZE (8 * 1024) -#define EXAMPLE_LVGL_TASK_PRIORITY 2 - -// 开启触摸屏支持 -#define CONFIG_EXAMPLE_LCD_TOUCH_ENABLED 0 - -// 添加 CST816 驱动代码 -#define CST816_I2C_ADDR 0x15 - -typedef struct { - uint16_t x; - uint16_t y; - uint8_t touched; -} cst816_data_t; - -static bool cst816_read_touch(cst816_data_t *data) { - uint8_t reg = 0x02; // 触摸点数寄存器 - uint8_t buffer[5]; - - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (CST816_I2C_ADDR << 1) | I2C_MASTER_WRITE, true); - i2c_master_write_byte(cmd, reg, true); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (CST816_I2C_ADDR << 1) | I2C_MASTER_READ, true); - i2c_master_read_byte(cmd, buffer, I2C_MASTER_ACK); - i2c_master_read_byte(cmd, buffer + 1, I2C_MASTER_ACK); - i2c_master_read_byte(cmd, buffer + 2, I2C_MASTER_ACK); - i2c_master_read_byte(cmd, buffer + 3, I2C_MASTER_ACK); - i2c_master_read_byte(cmd, buffer + 4, I2C_MASTER_NACK); - i2c_master_stop(cmd); - - esp_err_t ret = - i2c_master_cmd_begin(TOUCH_I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); - i2c_cmd_link_delete(cmd); - - if (ret != ESP_OK) { - return false; - } - - data->touched = buffer[0] > 0; - if (data->touched) { - data->x = ((buffer[1] & 0x0F) << 8) | buffer[2]; - data->y = ((buffer[3] & 0x0F) << 8) | buffer[4]; - return true; - } - return false; -} - -// 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; - -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t s_wifi_event_group; - -/* The event group allows multiple bits for each event, but we only care about - * two events: - * - we are connected to the AP with an IP - * - we failed to connect after the maximum amount of retries */ -#define WIFI_CONNECTED_BIT BIT0 -#define WIFI_FAIL_BIT BIT1 - -static const char *TAG = "example"; -// static const char *TAG = "wifi station"; - -static int s_retry_num = 0; - -// extern void example_lvgl_demo_ui(lv_disp_t *disp); - -/** - * @brief 设置 LCD 背光亮度 - * @param brightness 亮度值 0-1023(0=灭, 1023=最亮) - */ -void lcd_backlight_set_brightness(uint16_t brightness) { - if (brightness > 1023) - brightness = 1023; - ESP_ERROR_CHECK( - ledc_set_duty(LEDC_LOW_SPEED_MODE, EXAMPLE_LCD_BK_LIGHT_CH, brightness)); - ESP_ERROR_CHECK( - ledc_update_duty(LEDC_LOW_SPEED_MODE, EXAMPLE_LCD_BK_LIGHT_CH)); -} - -static bool -example_notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, - esp_lcd_panel_io_event_data_t *edata, - void *user_ctx) { - lv_display_t *disp = (lv_display_t *)user_ctx; - lv_display_flush_ready(disp); - return false; -} - -/* Rotate display and touch, when rotated screen in LVGL. Called when driver - * parameters are updated. */ -static void example_lvgl_port_update_callback(lv_display_t *disp) { - esp_lcd_panel_handle_t panel_handle = lv_display_get_user_data(disp); - lv_display_rotation_t rotation = lv_display_get_rotation(disp); - - switch (rotation) { - case LV_DISPLAY_ROTATION_0: - // Rotate LCD display - esp_lcd_panel_swap_xy(panel_handle, false); - esp_lcd_panel_mirror(panel_handle, true, false); - break; - case LV_DISPLAY_ROTATION_90: - // Rotate LCD display - esp_lcd_panel_swap_xy(panel_handle, true); - esp_lcd_panel_mirror(panel_handle, true, true); - break; - case LV_DISPLAY_ROTATION_180: - // Rotate LCD display - esp_lcd_panel_swap_xy(panel_handle, false); - esp_lcd_panel_mirror(panel_handle, false, true); - break; - case LV_DISPLAY_ROTATION_270: - // Rotate LCD display - esp_lcd_panel_swap_xy(panel_handle, true); - esp_lcd_panel_mirror(panel_handle, false, false); - break; - } -} - -static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, - uint8_t *px_map) { - // example_lvgl_port_update_callback(disp); - esp_lcd_panel_handle_t panel_handle = lv_display_get_user_data(disp); - int offsetx1 = area->x1; - int offsetx2 = area->x2; - int offsety1 = area->y1; - int offsety2 = area->y2; - // because SPI LCD is big-endian, we need to swap the RGB bytes order - lv_draw_sw_rgb565_swap(px_map, - (offsetx2 + 1 - offsetx1) * (offsety2 + 1 - offsety1)); - // copy a buffer's content to a specific area of the display - esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, - offsety2 + 1, px_map); -} - -#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED -static void example_lvgl_touch_cb(lv_indev_t *indev, lv_indev_data_t *data) { - uint16_t touchpad_x[1] = {0}; - uint16_t touchpad_y[1] = {0}; - uint8_t touchpad_cnt = 0; - - esp_lcd_touch_handle_t touch_pad = lv_indev_get_user_data(indev); - esp_lcd_touch_read_data(touch_pad); - /* Get coordinates */ - bool touchpad_pressed = esp_lcd_touch_get_coordinates( - touch_pad, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1); - - if (touchpad_pressed && touchpad_cnt > 0) { - data->point.x = touchpad_x[0]; - data->point.y = touchpad_y[0]; - data->state = LV_INDEV_STATE_PRESSED; - } else { - data->state = LV_INDEV_STATE_RELEASED; - } -} -#endif - -static void example_increase_lvgl_tick(void *arg) { - /* Tell LVGL how many milliseconds has elapsed */ - lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS); -} - -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 triggering a task watch dog time out - time_till_next_ms = MAX(time_till_next_ms, EXAMPLE_LVGL_TASK_MIN_DELAY_MS); - // in case of lvgl display not ready yet - time_till_next_ms = MIN(time_till_next_ms, EXAMPLE_LVGL_TASK_MAX_DELAY_MS); - usleep(1000 * time_till_next_ms); - } -} - -static void event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) { - if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { - esp_wifi_connect(); - } else if (event_base == WIFI_EVENT && - event_id == WIFI_EVENT_STA_DISCONNECTED) { - if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { - esp_wifi_connect(); - s_retry_num++; - ESP_LOGI(TAG, "retry to connect to the AP"); - } else { - xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); - ESP_LOGI(TAG, "connect to the AP fail"); - } - } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { - ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; - ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); - s_retry_num = 0; - xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); - } -} - -void wifi_init_sta(void) { - s_wifi_event_group = xEventGroupCreate(); - - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - esp_netif_create_default_wifi_sta(); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - - esp_event_handler_instance_t instance_any_id; - esp_event_handler_instance_t instance_got_ip; - ESP_ERROR_CHECK(esp_event_handler_instance_register( - WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id)); - ESP_ERROR_CHECK(esp_event_handler_instance_register( - IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip)); - - wifi_config_t wifi_config = { - .sta = - { - .ssid = EXAMPLE_ESP_WIFI_SSID, - .password = EXAMPLE_ESP_WIFI_PASS, - .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD, - .sae_pwe_h2e = ESP_WIFI_SAE_MODE, - .sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER, - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); - - ESP_LOGI(TAG, "wifi_init_sta finished. Connecting to AP in background..."); -} - -void app_main(void) { - - esp_log_level_set("*", ESP_LOG_INFO); - - // ESP_LOGI(TAG, "Turn off LCD backlight"); - // gpio_config_t bk_gpio_config = { - // .mode = GPIO_MODE_OUTPUT, - // .pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT}; - // ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); - - ESP_LOGI(TAG, "Configure LCD backlight PWM"); - ledc_timer_config_t ledc_timer = { - .speed_mode = LEDC_LOW_SPEED_MODE, - .timer_num = EXAMPLE_LCD_BK_LIGHT_TIMER, - .duty_resolution = LEDC_TIMER_10_BIT, // 10位分辨率 (0-1023) - .freq_hz = EXAMPLE_LCD_BK_LIGHT_FREQ, - .clk_cfg = LEDC_AUTO_CLK, - }; - ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); - - ledc_channel_config_t ledc_channel = { - .speed_mode = LEDC_LOW_SPEED_MODE, - .channel = EXAMPLE_LCD_BK_LIGHT_CH, - .timer_sel = EXAMPLE_LCD_BK_LIGHT_TIMER, - .intr_type = LEDC_INTR_DISABLE, - .gpio_num = EXAMPLE_PIN_NUM_BK_LIGHT, - .duty = 0, // 初始为 0(关闭) - .hpoint = 0, - }; - ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); - - ESP_LOGI(TAG, "Initialize SPI bus"); - spi_bus_config_t buscfg = { - .sclk_io_num = EXAMPLE_PIN_NUM_SCLK, - .mosi_io_num = EXAMPLE_PIN_NUM_MOSI, - .miso_io_num = EXAMPLE_PIN_NUM_MISO, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = EXAMPLE_LCD_H_RES * 80 * sizeof(uint16_t), - }; - ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO)); - - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_lcd_panel_io_spi_config_t io_config = { - .dc_gpio_num = EXAMPLE_PIN_NUM_LCD_DC, - .cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS, - .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, - .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS, - .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS, - .spi_mode = 0, - .trans_queue_depth = 10, - }; - // Attach the LCD to the SPI bus - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(LCD_HOST, &io_config, &io_handle)); - - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR, - .bits_per_pixel = 16, - }; - ESP_LOGI(TAG, "Install ST7789 panel driver"); - ESP_ERROR_CHECK( - esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, false)); - - // user can flush pre-defined pattern to the screen before we turn on the - // screen or backlight - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); - - ESP_LOGI(TAG, "Turn on LCD backlight"); - gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL); - // 设置背光亮度为 100%(占空比 1023/1023) - // lcd_backlight_set_brightness(1023); - // lcd_backlight_set_brightness(1023); - // while(1) { - // vTaskDelay(pdMS_TO_TICKS(1000)); - // } - // ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, EXAMPLE_LCD_BK_LIGHT_CH, - // 1023)); ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, - // EXAMPLE_LCD_BK_LIGHT_CH)); - - ESP_LOGI(TAG, "Initialize LVGL library"); - lv_init(); - - // create a lvgl display - lv_display_t *display = - lv_display_create(EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES); - - // alloc draw buffers used by LVGL - // it's recommended to choose the size of the draw buffer(s) to be at least - // 1/10 screen sized - size_t draw_buffer_sz = - EXAMPLE_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES * sizeof(lv_color16_t); - - void *buf1 = spi_bus_dma_memory_alloc(LCD_HOST, draw_buffer_sz, 0); - assert(buf1); - void *buf2 = spi_bus_dma_memory_alloc(LCD_HOST, draw_buffer_sz, 0); - assert(buf2); - // initialize LVGL draw buffers - lv_display_set_buffers(display, buf1, buf2, draw_buffer_sz, - LV_DISPLAY_RENDER_MODE_PARTIAL); - // associate the mipi 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); - // 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, "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, - EXAMPLE_LVGL_TICK_PERIOD_MS * 1000)); - - ESP_LOGI( - TAG, - "Register io panel event callback for LVGL flush ready notification"); - const esp_lcd_panel_io_callbacks_t cbs = { - .on_color_trans_done = example_notify_lvgl_flush_ready, - }; - /* Register done callback */ - ESP_ERROR_CHECK( - esp_lcd_panel_io_register_event_callbacks(io_handle, &cbs, display)); - -#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED - // 仅在触摸启用时初始化 I2C - ESP_LOGI(TAG, "Initialize I2C for touch"); - i2c_config_t i2c_conf = { - .mode = I2C_MODE_MASTER, - .sda_io_num = EXAMPLE_PIN_NUM_TOUCH_SDA, - .scl_io_num = EXAMPLE_PIN_NUM_TOUCH_SCL, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = TOUCH_I2C_MASTER_FREQ_HZ, - }; - ESP_ERROR_CHECK(i2c_param_config(TOUCH_I2C_MASTER_NUM, &i2c_conf)); - ESP_ERROR_CHECK( - i2c_driver_install(TOUCH_I2C_MASTER_NUM, I2C_MODE_MASTER, 0, 0, 0)); - - ESP_LOGI(TAG, "Initialize touch controller CST816"); - - esp_lcd_touch_handle_t tp = NULL; - esp_lcd_touch_config_t tp_cfg = { - .x_max = EXAMPLE_LCD_H_RES, - .y_max = EXAMPLE_LCD_V_RES, - .rst_gpio_num = EXAMPLE_PIN_NUM_TOUCH_RST, - .int_gpio_num = EXAMPLE_PIN_NUM_TOUCH_INT, - .flags = - { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - - // CST816 使用 I2C 接口 - ESP_ERROR_CHECK( - esp_lcd_touch_new_i2c_cst816(TOUCH_I2C_MASTER_NUM, &tp_cfg, &tp)); - - static lv_indev_t *indev; - indev = lv_indev_create(); - lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); - lv_indev_set_display(indev, display); - lv_indev_set_user_data(indev, tp); - lv_indev_set_read_cb(indev, example_lvgl_touch_cb); -#endif - - ESP_LOGI(TAG, "Create LVGL task"); - xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, - NULL, EXAMPLE_LVGL_TASK_PRIORITY, NULL); - - ESP_LOGI(TAG, "Lock the mutex due to the LVGL APIs are not thread-safe"); - // Lock the mutex due to the LVGL APIs are not thread-safe - _lock_acquire(&lvgl_api_lock); - // example_lvgl_demo_ui(display); - ui_init(); - _lock_release(&lvgl_api_lock); - - // Initialize NVS - 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); - - if (CONFIG_LOG_MAXIMUM_LEVEL > CONFIG_LOG_DEFAULT_LEVEL) { - /* If you only want to open more logs in the wifi module, you need to make - * the max level greater than the default level, and call - * esp_log_level_set() before esp_wifi_init() to improve the log level of - * the wifi module. */ - esp_log_level_set("wifi", CONFIG_LOG_MAXIMUM_LEVEL); - } - - ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); - wifi_init_sta(); -} diff --git a/main/services/wifi_manager.c b/main/services/wifi_manager.c new file mode 100644 index 0000000..26c6337 --- /dev/null +++ b/main/services/wifi_manager.c @@ -0,0 +1,116 @@ +#include "wifi_manager.h" + +#include "esp_event.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_wifi.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "freertos/task.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + +#define WIFI_SSID CONFIG_ESP_WIFI_SSID +#define WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define WIFI_MAX_RETRY CONFIG_ESP_MAXIMUM_RETRY + +#if CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HUNT_AND_PECK +#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK +#define H2E_IDENTIFIER "" +#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HASH_TO_ELEMENT +#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT +#define H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID +#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_BOTH +#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH +#define H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID +#endif + +#if CONFIG_ESP_WIFI_AUTH_OPEN +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN +#elif CONFIG_ESP_WIFI_AUTH_WEP +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP +#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK +#endif + +static const char *TAG = "wifi_manager"; + +static EventGroupHandle_t s_wifi_event_group; +static int s_retry_num = 0; + +static void event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + (void)arg; + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } else if (event_base == WIFI_EVENT && + event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < WIFI_MAX_RETRY) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } else { + xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + ESP_LOGI(TAG, "connect to the AP fail"); + } + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); + s_retry_num = 0; + xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } +} + +void wifi_manager_init(void) +{ + s_wifi_event_group = xEventGroupCreate(); + + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register( + WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id)); + ESP_ERROR_CHECK(esp_event_handler_instance_register( + IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = WIFI_SSID, + .password = WIFI_PASS, + .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD, + .sae_pwe_h2e = ESP_WIFI_SAE_MODE, + .sae_h2e_identifier = H2E_IDENTIFIER, + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + if (CONFIG_LOG_MAXIMUM_LEVEL > CONFIG_LOG_DEFAULT_LEVEL) { + esp_log_level_set("wifi", CONFIG_LOG_MAXIMUM_LEVEL); + } + + ESP_LOGI(TAG, "WiFi STA started, connecting in background..."); +} diff --git a/main/services/wifi_manager.h b/main/services/wifi_manager.h new file mode 100644 index 0000000..f024f84 --- /dev/null +++ b/main/services/wifi_manager.h @@ -0,0 +1,3 @@ +#pragma once + +void wifi_manager_init(void); diff --git a/main/filelist.txt b/main/ui/filelist.txt similarity index 60% rename from main/filelist.txt rename to main/ui/filelist.txt index 92447dd..f271aa0 100644 --- a/main/filelist.txt +++ b/main/ui/filelist.txt @@ -1,4 +1,4 @@ screens/ui_Screen1.c ui.c -components/ui_comp_hook.c +widgets/ui_comp_hook.c ui_helpers.c diff --git a/main/ui/fonts/.gitkeep b/main/ui/fonts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/main/ui/images/.gitkeep b/main/ui/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/main/project.info b/main/ui/project.info similarity index 100% rename from main/project.info rename to main/ui/project.info diff --git a/main/screens/ui_Screen1.c b/main/ui/screens/ui_Screen1.c similarity index 100% rename from main/screens/ui_Screen1.c rename to main/ui/screens/ui_Screen1.c diff --git a/main/screens/ui_Screen1.h b/main/ui/screens/ui_Screen1.h similarity index 99% rename from main/screens/ui_Screen1.h rename to main/ui/screens/ui_Screen1.h index ab3196f..ae3f0a4 100644 --- a/main/screens/ui_Screen1.h +++ b/main/ui/screens/ui_Screen1.h @@ -23,4 +23,3 @@ extern lv_obj_t * uic_Calendar1; #endif #endif - diff --git a/main/ui.c b/main/ui/ui.c similarity index 100% rename from main/ui.c rename to main/ui/ui.c diff --git a/main/ui.h b/main/ui/ui.h similarity index 100% rename from main/ui.h rename to main/ui/ui.h diff --git a/main/ui_events.h b/main/ui/ui_events.h similarity index 100% rename from main/ui_events.h rename to main/ui/ui_events.h diff --git a/main/ui_helpers.c b/main/ui/ui_helpers.c similarity index 100% rename from main/ui_helpers.c rename to main/ui/ui_helpers.c diff --git a/main/ui_helpers.h b/main/ui/ui_helpers.h similarity index 100% rename from main/ui_helpers.h rename to main/ui/ui_helpers.h diff --git a/main/components/ui_comp_hook.c b/main/ui/widgets/ui_comp_hook.c similarity index 99% rename from main/components/ui_comp_hook.c rename to main/ui/widgets/ui_comp_hook.c index a745eac..c8c28fd 100644 --- a/main/components/ui_comp_hook.c +++ b/main/ui/widgets/ui_comp_hook.c @@ -2,4 +2,3 @@ // SquareLine Studio version: SquareLine Studio 1.6.1 // LVGL version: 9.2.2 // Project name: HeavenlyHeroStar -