Fire_RT1021_Watch/src/app_lvgl.c
Yilin Sun 541b76d79a
All checks were successful
continuous-integration/drone/push Build is passing
Initial LVGL support.
Signed-off-by: Yilin Sun <imi415@imi.moe>
2024-03-16 02:01:48 +08:00

121 lines
3.0 KiB
C

/* FreeRTOS */
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
/* LVGL */
#include "lvgl.h"
/* LCD */
#include "epd-spi/panel/lcd_tk0096f611.h"
/* App */
#include "app_lcd_impl.h"
#include "app_lvgl.h"
#define APP_LVGL_LCD_DIR LCD_ST7789_DIR_90
#define APP_LVGL_LCD_BUF_SIZE (160 * 20)
static lcd_st7789_t s_lcd = {
.cb =
{
.write_command_cb = app_lcd_impl_write_command,
.write_data_cb = app_lcd_impl_write_data,
.delay_cb = app_lcd_impl_delay,
},
};
static SemaphoreHandle_t s_lvgl_semphr = NULL;
static uint16_t s_lcd_buffer[APP_LVGL_LCD_BUF_SIZE];
static uint32_t app_lvgl_get_tick_cb(void);
static void app_lvgl_lcd_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map);
static void app_lvgl_task(void *arguments);
int app_lvgl_init(void) {
s_lvgl_semphr = xSemaphoreCreateBinary();
if (s_lvgl_semphr == NULL) {
return -1;
}
xSemaphoreGive(s_lvgl_semphr);
app_lcd_impl_init(NULL);
lcd_st7789_init(&s_lcd, &lcd_tk0096_panel_config);
lcd_st7789_set_direction(&s_lcd, APP_LVGL_LCD_DIR);
lcd_st7789_set_pixel_format(&s_lcd, LCD_ST7789_RGB565);
lcd_st7789_enable_display(&s_lcd, true);
lv_init();
lv_tick_set_cb(app_lvgl_get_tick_cb);
uint16_t hor_res;
uint16_t ver_res;
if (s_lcd.direction == LCD_ST7789_DIR_0 || s_lcd.direction == LCD_ST7789_DIR_180) {
hor_res = lcd_tk0096_panel_config.size_x;
ver_res = lcd_tk0096_panel_config.size_y;
} else {
hor_res = lcd_tk0096_panel_config.size_y;
ver_res = lcd_tk0096_panel_config.size_x;
}
lv_display_t *display = lv_display_create(hor_res, ver_res);
lv_display_set_flush_cb(display, app_lvgl_lcd_flush_cb);
lv_display_set_buffers(display, s_lcd_buffer, NULL, sizeof(s_lcd_buffer), LV_DISPLAY_RENDER_MODE_PARTIAL);
if (xTaskCreate(app_lvgl_task, "LVGL", 2048, NULL, 3, NULL) != pdPASS) {
lv_deinit();
vSemaphoreDelete(s_lvgl_semphr);
return -1;
}
return 0;
}
bool app_lvgl_lock(uint32_t timeout_ms) {
if (xSemaphoreTake(s_lvgl_semphr, pdMS_TO_TICKS(timeout_ms)) != pdPASS) {
return false;
}
return true;
}
void app_lvgl_unlock(void) {
xSemaphoreGive(s_lvgl_semphr);
}
static uint32_t app_lvgl_get_tick_cb(void) {
return xTaskGetTickCount();
}
static void app_lvgl_lcd_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
epd_coord_t coord = {
.x_start = area->x1,
.x_end = area->x2,
.y_start = area->y1,
.y_end = area->y2,
};
lv_draw_sw_rgb565_swap(px_map, (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1));
lcd_st7789_load(&s_lcd, &coord, px_map);
lv_display_flush_ready(disp);
}
static void app_lvgl_task(void *arguments) {
for (;;) {
if (app_lvgl_lock(portMAX_DELAY)) {
lv_task_handler();
app_lvgl_unlock();
}
vTaskDelay(pdMS_TO_TICKS(5));
}
}