#include #include "esp_err.h" #include "esp_heap_caps.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "lvgl.h" #include "battery_monitor.h" #include "metrics_ble.h" #include "metrics_serial.h" #include "st7305_rlcd.h" #include "temp_humidity_monitor.h" #include "ui_screen.h" static const char *TAG = "rlcd_app"; static void lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *color_p) { uint16_t *buffer = (uint16_t *)color_p; for (int y = area->y1; y <= area->y2; y++) { for (int x = area->x1; x <= area->x2; x++) { uint8_t color = (*buffer < 0x7FFF) ? ST7305_COLOR_BLACK : ST7305_COLOR_WHITE; st7305_rlcd_set_pixel(x, y, color); buffer++; } } st7305_rlcd_flush(); lv_display_flush_ready(disp); } static void lvgl_tick_task(void *arg) { (void)arg; while (1) { vTaskDelay(pdMS_TO_TICKS(5)); lv_lock(); lv_tick_inc(5); lv_unlock(); } } static esp_err_t init_lvgl(void) { lv_init(); lv_display_t *disp = lv_display_create(st7305_rlcd_get_width(), st7305_rlcd_get_height()); lv_display_set_flush_cb(disp, lvgl_flush_cb); size_t buffer_size = LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565) * st7305_rlcd_get_width() * st7305_rlcd_get_height(); uint8_t *buffer = (uint8_t *)heap_caps_malloc(buffer_size, MALLOC_CAP_SPIRAM); if (buffer == NULL) { ESP_LOGE(TAG, "Failed to allocate LVGL buffer."); return ESP_ERR_NO_MEM; } lv_display_set_buffers(disp, buffer, NULL, buffer_size, LV_DISPLAY_RENDER_MODE_PARTIAL); xTaskCreate(lvgl_tick_task, "lv_tick", 4096, NULL, 1, NULL); return ESP_OK; } void app_main(void) { ESP_LOGI(TAG, "Starting ESP32-S3-RLCD workbench firmware."); ESP_ERROR_CHECK(st7305_rlcd_init()); ESP_ERROR_CHECK(init_lvgl()); lv_lock(); ui_screen_create(); lv_unlock(); metrics_serial_start(); metrics_ble_start(); battery_monitor_start(); temp_humidity_monitor_start(); int frame_counter = 0; uint32_t ble_ui_update_count = 0; while (1) { vTaskDelay(pdMS_TO_TICKS(30)); ui_metrics_t metrics; if (metrics_ble_take_latest(&metrics)) { ui_screen_update_metrics_from_source(&metrics, "BLE"); ble_ui_update_count++; if ((ble_ui_update_count % 10) == 0) { ESP_LOGI(TAG, "BLE UI updated: %lu", (unsigned long)ble_ui_update_count); } } if (metrics_serial_take_latest(&metrics)) { ui_screen_update_metrics_from_source(&metrics, "USB"); } int battery_percent = 0; int battery_mv = 0; if (battery_monitor_take_latest(&battery_percent, &battery_mv)) { ui_screen_update_battery(battery_percent, battery_mv); } int temperature_c10 = 0; int humidity_percent = 0; if (temp_humidity_monitor_take_latest(&temperature_c10, &humidity_percent)) { ui_screen_update_environment(temperature_c10, humidity_percent); } lv_lock(); lv_timer_handler(); frame_counter++; if (frame_counter >= 33) { frame_counter = 0; ui_screen_tick(); } lv_unlock(); } }