164 lines
5.6 KiB
C
164 lines
5.6 KiB
C
#include <stdio.h>
|
|
#include "meteofrance.h"
|
|
#include "eventsManager.h"
|
|
#include "lvgl.h"
|
|
#include "esp_log.h"
|
|
|
|
#include "esp_heap_caps.h"
|
|
extern EventGroupHandle_t domotic_event_group;
|
|
|
|
/**
|
|
* 32-bit and 16-bit colors are currently supported by QEMU RGB Panel
|
|
*/
|
|
#if CONFIG_LV_COLOR_DEPTH_32
|
|
#define CURRENT_COLOR_DEPTH RGB_QEMU_BPP_32
|
|
#elif CONFIG_LV_COLOR_DEPTH_16
|
|
#define CURRENT_COLOR_DEPTH RGB_QEMU_BPP_16
|
|
#else
|
|
#error "QEMU RGB Panel only supports 32-bit and 16-bit colors, please enable LV_COLOR_DEPTH_32 or LV_COLOR_DEPTH_16"
|
|
#endif
|
|
|
|
// The pixel number in horizontal and vertical
|
|
#define EXAMPLE_LCD_H_RES 800
|
|
#define EXAMPLE_LCD_V_RES 480
|
|
|
|
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
|
#define EXAMPLE_LVGL_TASK_MAX_DELAY_MS 500
|
|
#define EXAMPLE_LVGL_TASK_MIN_DELAY_MS 1
|
|
#define EXAMPLE_LVGL_TASK_STACK_SIZE (10 * 1024)
|
|
#define EXAMPLE_LVGL_TASK_PRIORITY 2
|
|
static const char *TAG = "example";
|
|
|
|
SemaphoreHandle_t lvgl_mux;
|
|
|
|
static void example_lvgl_flush_cb(lv_display_t *drv, const lv_area_t *area, unsigned char * color_map)
|
|
{
|
|
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data;
|
|
int offsetx1 = area->x1;
|
|
int offsetx2 = area->x2;
|
|
int offsety1 = area->y1;
|
|
int offsety2 = area->y2;
|
|
// pass the draw buffer to the driver
|
|
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
|
|
lv_disp_flush_ready(drv);
|
|
}
|
|
|
|
static void example_increase_lvgl_tick(void *arg)
|
|
{
|
|
/* Tell LVGL how many milliseconds has elapsed */
|
|
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
|
}
|
|
|
|
bool example_lvgl_lock(int timeout_ms)
|
|
{
|
|
// Convert timeout in milliseconds to FreeRTOS ticks
|
|
// If `timeout_ms` is set to -1, the program will block until the condition is met
|
|
const TickType_t timeout_ticks = (timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
|
return xSemaphoreTakeRecursive(lvgl_mux, timeout_ticks) == pdTRUE;
|
|
}
|
|
|
|
void example_lvgl_unlock(void)
|
|
{
|
|
xSemaphoreGiveRecursive(lvgl_mux);
|
|
}
|
|
|
|
static void example_lvgl_port_task(void *arg)
|
|
{
|
|
ESP_LOGI(TAG, "Starting LVGL task");
|
|
uint32_t task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS;
|
|
while (1)
|
|
{
|
|
// Lock the mutex due to the LVGL APIs are not thread-safe
|
|
if (example_lvgl_lock(-1))
|
|
{
|
|
task_delay_ms = lv_timer_handler();
|
|
// Release the mutex
|
|
example_lvgl_unlock();
|
|
}
|
|
if (task_delay_ms > EXAMPLE_LVGL_TASK_MAX_DELAY_MS)
|
|
{
|
|
task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS;
|
|
}
|
|
else if (task_delay_ms < EXAMPLE_LVGL_TASK_MIN_DELAY_MS)
|
|
{
|
|
task_delay_ms = EXAMPLE_LVGL_TASK_MIN_DELAY_MS;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(task_delay_ms));
|
|
}
|
|
}
|
|
|
|
static size_t example_lvgl_get_buffers(esp_lcd_panel_handle_t panel_handle, void **buf1, void **buf2)
|
|
{
|
|
if (buf2)
|
|
{
|
|
*buf2 = NULL;
|
|
}
|
|
#if CONFIG_EXAMPLE_QEMU_RGB_PANEL_DEDIC_FB
|
|
ESP_LOGI(TAG, "Use QEMU dedicated frame buffer as LVGL draw buffer");
|
|
ESP_ERROR_CHECK(esp_lcd_rgb_qemu_get_frame_buffer(panel_handle, buf1));
|
|
return EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES;
|
|
#else
|
|
ESP_LOGI(TAG, "Allocate separate LVGL draw buffer");
|
|
/* Allocate 10 horizontal lines as the frame buffer */
|
|
*buf1 = malloc(EXAMPLE_LCD_H_RES * 10 * sizeof(lv_color_t));
|
|
assert(*buf1);
|
|
return EXAMPLE_LCD_H_RES * 10;
|
|
#endif // CONFIG_EXAMPLE_DOUBLE_FB
|
|
}
|
|
|
|
void app_main()
|
|
{
|
|
printf(">>> app_main() from test_main.c under Linux\n");
|
|
startEvtManager();
|
|
|
|
ESP_LOGI(TAG, "Install RGB LCD panel driver");
|
|
esp_lcd_panel_handle_t panel_handle = NULL;
|
|
esp_lcd_rgb_qemu_config_t panel_config = {
|
|
.width = EXAMPLE_LCD_H_RES,
|
|
.height = EXAMPLE_LCD_V_RES,
|
|
.bpp = CURRENT_COLOR_DEPTH,
|
|
};
|
|
ESP_ERROR_CHECK(esp_lcd_new_rgb_qemu(&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, "Free internal heap: %d", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
|
ESP_LOGI(TAG, "Free SPIRAM heap: %d", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
|
|
|
ESP_LOGI(TAG, "Initialize LVGL library");
|
|
lv_init();
|
|
lv_display_t *disp = lv_display_create(EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES);
|
|
disp->user_data=panel_handle;
|
|
lv_display_set_flush_cb(disp, example_lvgl_flush_cb);
|
|
void *buf1 = NULL;
|
|
void *buf2 = NULL;
|
|
const size_t buf_pixels = example_lvgl_get_buffers(panel_handle, &buf1, &buf2);
|
|
lv_display_set_buffers(disp, buf1, buf2, EXAMPLE_LCD_H_RES * 10 * sizeof(lv_color_t), LV_DISP_RENDER_MODE_PARTIAL);
|
|
|
|
lvgl_mux = xSemaphoreCreateRecursiveMutex();
|
|
assert(lvgl_mux);
|
|
|
|
/* lv_sdl_mouse_create();
|
|
lv_sdl_keyboard_create();
|
|
lv_sdl_mousewheel_create();
|
|
lv_sdl_mousewheel_create();
|
|
*/
|
|
|
|
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, "Create LVGL task");
|
|
xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, NULL, EXAMPLE_LVGL_TASK_PRIORITY, NULL);
|
|
|
|
xTaskCreate(drawIhm, "LVGL", 128 * 1024, getIHMQueueHandle(), 3, NULL);
|
|
//initialise_weather_data_retrieval(20, domotic_event_group);
|
|
printf("<<< end app_main()\n");
|
|
} |