generated from Embedded_Projects/Landzo_K60Z_LwIP
208 lines
4.9 KiB
C
208 lines
4.9 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
|
|
|
|
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,
|
|
},
|
|
.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 * 20];
|
|
__attribute((section(".lvgl_buffer"))) static lv_color_t s_lvgl_buf_2[LVGL_RES_HOR * 20];
|
|
|
|
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) {
|
|
FIL *fp = pvPortMalloc(sizeof(FIL));
|
|
if (fp == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
char *ff_path = pvPortMalloc(255);
|
|
if (ff_path == NULL) {
|
|
vPortFree(fp);
|
|
return NULL;
|
|
}
|
|
|
|
snprintf(ff_path, 255, LVGL_FS_BASE "%s", path);
|
|
FRESULT res = f_open(fp, ff_path, FA_READ);
|
|
if (res != FR_OK) {
|
|
vPortFree(ff_path);
|
|
vPortFree(fp);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
vPortFree(ff_path);
|
|
|
|
return fp;
|
|
}
|
|
|
|
static lv_fs_res_t lvgl_fs_close_cb(lv_fs_drv_t *drv, void *file_p) {
|
|
FIL *fp = file_p;
|
|
|
|
FRESULT res = f_close(fp);
|
|
|
|
vPortFree(fp);
|
|
|
|
if (res != FR_OK) {
|
|
return LV_FS_RES_FS_ERR;
|
|
}
|
|
|
|
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) {
|
|
FIL *fp = file_p;
|
|
|
|
FRESULT res = f_read(fp, buf, btr, (unsigned int *)br);
|
|
if (res != FR_OK) {
|
|
return LV_FS_RES_FS_ERR;
|
|
}
|
|
|
|
return LV_FS_RES_OK;
|
|
}
|
|
|
|
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) {
|
|
FRESULT res;
|
|
|
|
FIL *fp = file_p;
|
|
|
|
uint32_t size = f_size(fp);
|
|
|
|
if (whence != LV_FS_SEEK_CUR) {
|
|
res = f_rewind(fp);
|
|
|
|
if (res != FR_OK) {
|
|
return LV_FS_RES_FS_ERR;
|
|
}
|
|
}
|
|
|
|
if (whence == LV_FS_SEEK_END) {
|
|
pos = (size - 1) - pos;
|
|
}
|
|
|
|
res = f_lseek(fp, pos);
|
|
if (res != FR_OK) {
|
|
return LV_FS_RES_FS_ERR;
|
|
}
|
|
|
|
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 * 10);
|
|
|
|
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.seek_cb = lvgl_fs_seek_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, 32, 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));
|
|
}
|
|
}
|