Landzo_K60Z_WebServer/src/lvgl_helpers.c

272 lines
7.1 KiB
C

#include <stdio.h>
/* LVGL */
#include "lvgl.h"
/* FreeRTOS */
#include "FreeRTOS.h"
#include "event_groups.h"
#include "semphr.h"
#include "task.h"
/* FatFS */
#include "ff.h"
/* LCD */
#include "epd-spi/panel/lcd_generic_ssd1289.h"
#include "lcd_impl.h"
#define LVGL_FS_BASE "0:/LV_ROOT/"
#define LVGL_RES_HOR 240
#define LVGL_RES_VER 320
#define LVGL_CACHE_DEPTH 40
SemaphoreHandle_t g_lvgl_semphr;
EventGroupHandle_t g_lvgl_event_group;
static lv_disp_draw_buf_t s_lvgl_disp_buf;
static lv_disp_drv_t s_lvgl_disp_drv;
static lv_fs_drv_t s_lvgl_fs_drv;
static lcd_impl_t s_lcd_impl;
static lcd_generic_ssd1289_t s_lcd = {
.cb =
{
.reset_cb = epd_impl_reset,
.write_command_cb = epd_impl_write_command,
.write_data_cb = epd_impl_write_data,
.delay_cb = epd_impl_delay,
},
.dir = LCD_GENERIC_SSD1289_DIR_VERTICAL,
.mode = LCD_GENERIC_SSD1289_MODE_XBRG8888,
.user_data = &s_lcd_impl,
};
__attribute((section(".lvgl_buffer"))) static lv_color_t s_lvgl_buf_1[LVGL_RES_HOR * LVGL_CACHE_DEPTH];
__attribute((section(".lvgl_buffer"))) static lv_color_t s_lvgl_buf_2[LVGL_RES_HOR * LVGL_CACHE_DEPTH];
void lvgl_task(void *pvParameters);
static void lvgl_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
lcd_generic_ssd1289_t *lcd = disp_drv->user_data;
epd_coord_t coord = {
.x_start = area->x1,
.x_end = area->x2,
.y_start = area->y1,
.y_end = area->y2,
};
lcd_generic_ssd1289_upload(lcd, &coord, (uint8_t *)color_p);
lv_disp_flush_ready(disp_drv);
}
static void lvgl_set_px_cb(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa) {
/* 4 bytes per pixel. */
uint32_t *px = (uint32_t *)&buf[(y * buf_w + x) * 4];
/* Set color */
*px = color.ch.green & 0xFFU;
*px |= (color.ch.red & 0xFFU) << 8U;
*px |= (color.ch.blue & 0xFFU) << 16U;
}
static void *lvgl_fs_open_cb(lv_fs_drv_t *drv, const char *path, lv_fs_mode_t mode) {
LV_UNUSED(drv);
uint8_t flags = 0;
if (mode == LV_FS_MODE_WR)
flags = FA_WRITE | FA_OPEN_ALWAYS;
else if (mode == LV_FS_MODE_RD)
flags = FA_READ;
else if (mode == (LV_FS_MODE_WR | LV_FS_MODE_RD))
flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
FIL *f = lv_mem_alloc(sizeof(FIL));
if (f == NULL) return NULL;
TCHAR *ff_path = lv_mem_alloc(sizeof(TCHAR) * 256);
if (ff_path == NULL) {
lv_mem_free(f);
return NULL;
}
snprintf(ff_path, 256, LVGL_FS_BASE "%s", path);
FRESULT res = f_open(f, ff_path, flags);
lv_mem_free(ff_path);
if (res == FR_OK) {
return f;
} else {
lv_mem_free(f);
return NULL;
}
}
static lv_fs_res_t lvgl_fs_close_cb(lv_fs_drv_t *drv, void *file_p) {
LV_UNUSED(drv);
f_close(file_p);
lv_mem_free(file_p);
return LV_FS_RES_OK;
}
static lv_fs_res_t lvgl_fs_read_cb(lv_fs_drv_t *drv, void *file_p, void *buf, uint32_t btr, uint32_t *br) {
LV_UNUSED(drv);
FRESULT res = f_read(file_p, buf, btr, (UINT *)br);
if (res == FR_OK)
return LV_FS_RES_OK;
else
return LV_FS_RES_UNKNOWN;
}
static lv_fs_res_t lvgl_fs_write_cb(lv_fs_drv_t *drv, void *file_p, const void *buf, uint32_t btw, uint32_t *bw) {
LV_UNUSED(drv);
FRESULT res = f_write(file_p, buf, btw, (UINT *)bw);
if (res == FR_OK)
return LV_FS_RES_OK;
else
return LV_FS_RES_UNKNOWN;
}
static lv_fs_res_t lvgl_fs_seek_cb(lv_fs_drv_t *drv, void *file_p, uint32_t pos, lv_fs_whence_t whence) {
LV_UNUSED(drv);
switch (whence) {
case LV_FS_SEEK_SET:
f_lseek(file_p, pos);
break;
case LV_FS_SEEK_CUR:
f_lseek(file_p, f_tell((FIL *)file_p) + pos);
break;
case LV_FS_SEEK_END:
f_lseek(file_p, f_size((FIL *)file_p) + pos);
break;
default:
break;
}
return LV_FS_RES_OK;
}
static lv_fs_res_t lvgl_fs_tell_cb(lv_fs_drv_t *drv, void *file_p, uint32_t *pos_p) {
LV_UNUSED(drv);
*pos_p = f_tell((FIL *)file_p);
return LV_FS_RES_OK;
}
static void *lvgl_fs_dir_open_cb(lv_fs_drv_t *drv, const char *path) {
LV_UNUSED(drv);
DIR *d = lv_mem_alloc(sizeof(DIR));
if (d == NULL) return NULL;
TCHAR *ff_path = lv_mem_alloc(sizeof(TCHAR) * 256);
if (ff_path == NULL) {
lv_mem_free(d);
return NULL;
}
snprintf(ff_path, 256, LVGL_FS_BASE "%s", path);
FRESULT res = f_opendir(d, ff_path);
lv_mem_free(ff_path);
if (res != FR_OK) {
lv_mem_free(d);
d = NULL;
}
return d;
}
static lv_fs_res_t lvgl_fs_dir_read_cb(lv_fs_drv_t *drv, void *dir_p, char *fn) {
LV_UNUSED(drv);
FRESULT res;
FILINFO fno;
fn[0] = '\0';
do {
res = f_readdir(dir_p, &fno);
if (res != FR_OK) return LV_FS_RES_UNKNOWN;
if (fno.fattrib & AM_DIR) {
fn[0] = '/';
strcpy(&fn[1], fno.fname);
} else
strcpy(fn, fno.fname);
} while (strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0);
return LV_FS_RES_OK;
}
static lv_fs_res_t lvgl_fs_dir_close_cb(lv_fs_drv_t *drv, void *dir_p) {
LV_UNUSED(drv);
f_closedir(dir_p);
lv_mem_free(dir_p);
return LV_FS_RES_OK;
}
int lvgl_setup(void) {
lv_init();
lv_disp_draw_buf_init(&s_lvgl_disp_buf, s_lvgl_buf_1, s_lvgl_buf_2, LVGL_RES_HOR * LVGL_CACHE_DEPTH);
epd_impl_init(&s_lcd_impl);
lcd_generic_ssd1289_init(&s_lcd);
lv_disp_drv_init(&s_lvgl_disp_drv);
s_lvgl_disp_drv.draw_buf = &s_lvgl_disp_buf;
s_lvgl_disp_drv.user_data = &s_lcd;
s_lvgl_disp_drv.flush_cb = lvgl_flush_cb;
s_lvgl_disp_drv.set_px_cb = lvgl_set_px_cb;
s_lvgl_disp_drv.hor_res = LVGL_RES_HOR;
s_lvgl_disp_drv.ver_res = LVGL_RES_VER;
lv_disp_drv_register(&s_lvgl_disp_drv);
lv_fs_drv_init(&s_lvgl_fs_drv);
s_lvgl_fs_drv.letter = 'A';
s_lvgl_fs_drv.open_cb = lvgl_fs_open_cb;
s_lvgl_fs_drv.close_cb = lvgl_fs_close_cb;
s_lvgl_fs_drv.read_cb = lvgl_fs_read_cb;
s_lvgl_fs_drv.write_cb = lvgl_fs_write_cb;
s_lvgl_fs_drv.seek_cb = lvgl_fs_seek_cb;
s_lvgl_fs_drv.tell_cb = lvgl_fs_tell_cb;
s_lvgl_fs_drv.dir_open_cb = lvgl_fs_dir_open_cb;
s_lvgl_fs_drv.dir_read_cb = lvgl_fs_dir_read_cb;
s_lvgl_fs_drv.dir_close_cb = lvgl_fs_dir_close_cb;
lv_fs_drv_register(&s_lvgl_fs_drv);
g_lvgl_semphr = xSemaphoreCreateBinary();
if (g_lvgl_semphr == NULL) {
return -1;
}
xSemaphoreGive(g_lvgl_semphr);
if (xTaskCreate(lvgl_task, "LVTASK", 2048, NULL, 13, NULL) != pdPASS) {
return -3;
}
return 0;
}
uint32_t lvgl_millis(void) {
return xTaskGetTickCount();
}
void lvgl_task(void *pvParameters) {
for (;;) {
if (xSemaphoreTake(g_lvgl_semphr, pdMS_TO_TICKS(150)) == pdTRUE) {
lv_timer_handler();
xSemaphoreGive(g_lvgl_semphr);
}
vTaskDelay(pdMS_TO_TICKS(15));
}
}