Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources

This commit is contained in:
2026-07-06 11:30:13 +08:00
commit e76462eeb7
3451 changed files with 1415300 additions and 0 deletions

View File

@@ -0,0 +1,724 @@
/**
* @file lv_port_disp_templ.c
*
*/
/*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
#if 1
/*********************
* INCLUDES
*********************/
#include "basic_include.h"
#include "lv_port_disp.h"
#include <stdbool.h>
#include "app_lcd/app_lcd.h"
#include "lib/heap/av_psram_heap.h"
#define LV_PORT_DISP_LINE (32)
/*********************
* DEFINES
*********************/
#if 0
#ifndef MY_DISP_HOR_RES
#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.
#define MY_DISP_HOR_RES 320
#endif
#ifndef MY_DISP_VER_RES
#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen height, default value 240 is used for now.
#define MY_DISP_VER_RES 240
#endif
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void disp_init(void);
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
static void disp_flush_rotate(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
static void lv_wait_cb(struct _lv_disp_drv_t * disp_drv)
{
os_sleep_ms(1);
}
//static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
// const lv_area_t * fill_area, lv_color_t color);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
///__psram_data uint8_t osd_menu565_buf[SCALE_HIGH*SCALE_WIDTH*2] __aligned(4);
uint8_t *osd_menu565_buf;
//__psram_data static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES] __aligned(4); /*A screen sized buffer*/
//__psram_data static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES] __aligned(4); /*Another screen sized buffer*/
// static lv_color_t *buf_3_1; /*A screen sized buffer*/
// static lv_color_t *buf_3_2; /*Another screen sized buffer*/
void lv_port_disp_init(void *stream,uint16_t w,uint16_t h,uint8_t rotate)
{
/*-------------------------
* Initialize your display
* -----------------------*/
disp_init();
/*-----------------------------
* Create a buffer for drawing
*----------------------------*/
/**
* LVGL requires a buffer where it internally draws the widgets.
* Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
* The buffer has to be greater than 1 display row
*
* There are 3 buffering configurations:
* 1. Create ONE buffer:
* LVGL will draw the display's content here and writes it to your display
*
* 2. Create TWO buffer:
* LVGL will draw the display's content to a buffer and writes it your display.
* You should use DMA to write the buffer's content to the display.
* It will enable LVGL to draw the next part of the screen to the other buffer while
* the data is being sent form the first buffer. It makes rendering and flushing parallel.
*
* 3. Double buffering
* Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
* This way LVGL will always provide the whole rendered screen in `flush_cb`
* and you only need to change the frame buffer's address.
*/
/* Example for 1) */
static lv_disp_draw_buf_t draw_buf_dsc_1;
/* Example for 2) */
// static lv_disp_draw_buf_t draw_buf_dsc_2;
// static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
// static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10]; /*An other buffer for 10 rows*/
// lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
/* Example for 3) also set disp_drv.full_refresh = 1 below*/
// static lv_disp_draw_buf_t draw_buf_dsc_3;
// static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*A screen sized buffer*/
// static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*Another screen sized buffer*/
// static lv_color_t *buf_3_1; /*A screen sized buffer*/
// static lv_color_t *buf_3_2; /*Another screen sized buffer*/
// buf_3_1 = (uint8*)malloc_psram(MY_DISP_HOR_RES * MY_DISP_VER_RES*2);
// buf_3_2 = (uint8*)malloc_psram(MY_DISP_HOR_RES * MY_DISP_VER_RES*2);
// lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2,
// MY_DISP_VER_RES * LV_VER_RES_MAX); /*Initialize the display buffer*/
/*-----------------------------------
* Register the display in LVGL
*----------------------------------*/
static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
lv_color_t *buf_1;
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
//重新配置一下是否旋转,由屏参数配置
if(rotate)
{
disp_drv.sw_rotate = 1;
}
else
{
disp_drv.sw_rotate = 0;
}
disp_drv.rotated = rotate;
//如果旋转,就使用单buf
if(disp_drv.sw_rotate)
{
buf_1 = (lv_color_t*)lv_malloc(w*LV_PORT_DISP_LINE*sizeof(lv_color_t));
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, w * LV_PORT_DISP_LINE); /*Initialize the display buffer*/
//旋转,需要中间层
osd_menu565_buf = (uint8_t *)lv_malloc(w*h*2);
disp_drv.flush_cb = disp_flush_rotate;
}
else
{
//非旋转,直接绘制就好了
disp_drv.direct_mode = 1;
buf_1 = (lv_color_t*)lv_malloc(w*h*sizeof(lv_color_t));
osd_menu565_buf = (uint8_t *)buf_1;
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, w * h); /*Initialize the display buffer*/
disp_drv.flush_cb = disp_flush;
}
/*Set up the functions to access to your display*/
/*Set the resolution of the display*/
disp_drv.hor_res = w;
disp_drv.ver_res = h;
disp_drv.user_data = stream;
disp_drv.disp_buf_len = w*h*sizeof(lv_color_t);
/*Used to copy the buffer's content to the display*/
disp_drv.wait_cb = lv_wait_cb;
/*Set a display buffer*/
disp_drv.draw_buf = &draw_buf_dsc_1;
/*Required for Example 3)*/
//disp_drv.full_refresh = 1;
/* Fill a memory array with a color if you have GPU.
* Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.
* But if you have a different GPU you can use with this callback.*/
//disp_drv.gpu_fill_cb = gpu_fill;
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
/*You code here*/
}
volatile bool disp_flush_enabled = true;
/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_enable_update(void)
{
disp_flush_enabled = true;
}
/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_disable_update(void)
{
disp_flush_enabled = false;
}
/*Flush the content of the internal buffer the specific area on the display
*You can use DMA or any hardware acceleration to do this operation in the background but
*'lv_disp_flush_ready()' has to be called when finished.*/
uint8_t disp_updata = 0;
//不需要旋转
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
lv_color_t *p_16;
p_16 = (lv_color_t*)osd_menu565_buf;
if(disp_drv->draw_buf->flushing_last)
{
sys_dcache_clean_range((uint32_t*)p_16, disp_drv->disp_buf_len);
disp_updata = 1;
}
lv_disp_flush_ready(disp_drv);
}
//旋转部分
static void disp_flush_rotate(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
lv_color_t *p_16;
p_16 = (lv_color_t*)osd_menu565_buf;
if(area->x1 == 0 && area->x2 == disp_drv->hor_res-1)
{
hw_memcpy(p_16+area->y1*disp_drv->hor_res,color_p,disp_drv->hor_res*(area->y2-area->y1+1) *sizeof(lv_color_t));
}
else
{
uint32_t y;
for(y = area->y1; y <= area->y2; y++)
{
hw_memcpy(p_16+y*disp_drv->hor_res+area->x1,color_p,(area->x2-area->x1+1)*sizeof(lv_color_t));
color_p += (area->x2-area->x1+1);
}
}
if(disp_drv->draw_buf->flushing_last)
{
sys_dcache_clean_range((uint32_t*)p_16, disp_drv->disp_buf_len);
disp_updata = 1;
}
lv_disp_flush_ready(disp_drv);
}
//msi的驱动中间层
#include "basic_include.h"
#include "lib/multimedia/msi.h"
#include "video_app_csc_msi.h"
int lv_vendor_get_rotate_callback(struct framebuff *fb)
{
int ret = 0;
#if LVGL_HW_CSC_2_LCD_VIDEO
ret = lv_disp_get_rotation(NULL);
if(ret)
{
fb->srcID = FRAMEBUFF_SOURCE_OSD_ENC;
}
else
{
fb->srcID = FRAMEBUFF_SOURCE_CSC;
}
#else
fb->srcID = FRAMEBUFF_SOURCE_OSD_ENC;
#endif
return ret;
}
static void force_full_refresh_timer_cb(lv_timer_t * t)
{
lv_disp_t *disp = lv_disp_get_default();
if(!disp) { lv_timer_del(t); return; }
os_printf("%s %d\n",__FUNCTION__,__LINE__);
/* 标记活动屏为失效以触发绘制(会走 full_refresh 路径)*/
lv_obj_invalidate(lv_disp_get_scr_act(disp));
/* 立即触发刷新(将在安全的上下文执行)*/
lv_refr_now(disp);
/* 只要一次性生效,恢复标志并删除定时器 */
lv_timer_del(t);
}
int lv_vendor_rotate_callback(int width, int height)
{
#if LVGL_HW_CSC_2_LCD_VIDEO
static int last_rotate = 0xff;
int ret = 0;
int rotate = 0;
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_GET_ENABLE, (uint32)&rotate);
if (rotate != last_rotate) {
if (last_rotate != 0xff) {
if (rotate) {
os_printf("------OSD ENCODE MODE-------- width:%d height:%d\n", width, height);
lv_disp_set_full_screen_rotation(NULL, LV_DISP_ROT_270, width, height); // 480 800
lv_timer_create(force_full_refresh_timer_cb, 1, NULL);
} else {
os_printf("------CSC VIDEO MODE--------width:%d height:%d\n", width, height);
lv_disp_set_full_screen_rotation(NULL, LV_DISP_ROT_NONE, width, height); // 800 480
lv_timer_create(force_full_refresh_timer_cb, 1, NULL);
}
ret = 1;
}
last_rotate = rotate;
} else {
ret = 0;
}
return ret;
#else
return 0;
#endif
}
//不需要旋转
static void disp_flush_msi(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
int ret;
lv_color_t *p_16;
p_16 = (lv_color_t*)osd_menu565_buf;
if(disp_drv->draw_buf->flushing_last)
{
struct msi *msi = (struct msi*)disp_drv->user_data;
struct framebuff *fb;
int count = 0;
disp_flush_again:
fb = lvgl_osd_msi_get_fb(msi);
if(fb)
{
struct encode_data_s_callback *callback = (struct encode_data_s_callback*)fb->priv;
callback->user_data = (void*)disp_drv;
callback->finish_cb = (osd_finish_cb)lv_disp_flush_ready;
callback->rot_flag = lv_vendor_get_rotate_callback(fb);
fb->data = (void*)p_16;
fb->len = disp_drv->disp_buf_len;
//回写空间
sys_dcache_clean_range((uint32_t*)fb->data, disp_drv->disp_buf_len);
ret = lv_vendor_rotate_callback(disp_drv->ver_res, disp_drv->hor_res);
if (ret) {
msi_delete_fb(msi, fb);
} else {
msi_output_fb(msi, fb);
}
}
//如果其他地方处理慢,要考虑丢帧了
else
{
if(++count%1000 == 0)
{
os_printf("%s drop frame\n",__FUNCTION__);
}
os_sleep_ms(1);
goto disp_flush_again;
}
}
else
{
lv_disp_flush_ready(disp_drv);
}
}
//旋转部分
static void disp_flush_rotate_msi(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
int ret;
lv_color_t *p_16;
p_16 = (lv_color_t*)osd_menu565_buf;
if(area->x1 == 0 && area->x2 == disp_drv->hor_res-1)
{
hw_memcpy_no_cache(p_16+area->y1*disp_drv->hor_res,color_p,disp_drv->hor_res*(area->y2-area->y1+1) *sizeof(lv_color_t));
}
else
{
uint32_t y;
for(y = area->y1; y <= area->y2; y++)
{
hw_memcpy_no_cache(p_16+y*disp_drv->hor_res+area->x1,color_p,(area->x2-area->x1+1)*sizeof(lv_color_t));
color_p += (area->x2-area->x1+1);
}
}
if(disp_drv->draw_buf->flushing_last)
{
struct msi *msi = (struct msi*)disp_drv->user_data;
struct framebuff *fb;
int count = 0;
disp_flush_rotate_msi_again:
fb = lvgl_osd_msi_get_fb(msi);
if(fb)
{
struct encode_data_s_callback *callback = (struct encode_data_s_callback*)fb->priv;
callback->user_data = (void*)disp_drv;
callback->finish_cb = (osd_finish_cb)lv_disp_flush_ready;
callback->rot_flag = lv_vendor_get_rotate_callback(fb);
fb->data = (void*)p_16;
fb->len = disp_drv->disp_buf_len;
ret = lv_vendor_rotate_callback(disp_drv->ver_res, disp_drv->hor_res);
if (ret) {
msi_delete_fb(msi, fb);
} else {
msi_output_fb(msi, fb);
}
}
//如果其他地方处理慢,要考虑丢帧了
else
{
if(++count%1000 == 0)
{
os_printf("%s drop frame\n",__FUNCTION__);
}
os_sleep_ms(1);
goto disp_flush_rotate_msi_again;
}
}
else
{
lv_disp_flush_ready(disp_drv);
}
}
#if DMA2D_EN
#include "hal/dma2d.h"
static void disp_flush_rotate_dma2d_msi(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
int ret = 0;
lv_color_t *p_16;
p_16 = (lv_color_t*)osd_menu565_buf;
static struct dma2d_device *dma2d_dev = NULL;
if(dma2d_dev == NULL){
dma2d_dev = (struct dma2d_device *)dev_get(HG_DMA2D_DEVID);
}
struct dma2d_blkcpy_param blkcpy;
sys_dcache_clean_range((uint32_t*)color_p, (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) * sizeof(lv_color_t));
// 使用 DMA2D 一次性拷贝整个区域
memset(&blkcpy, 0, sizeof(struct dma2d_blkcpy_param));
blkcpy.src_addr = (uint32_t)color_p;
blkcpy.dst_addr = (uint32_t)(p_16 + area->y1 * disp_drv->hor_res + area->x1);
blkcpy.color_mode = DMA2D_COLOR_TYPE_RGB565;
blkcpy.src_pixel_width = area->x2 - area->x1 + 1;
blkcpy.dst_pixel_width = disp_drv->hor_res;
blkcpy.blk_pixel_width = area->x2 - area->x1 + 1;
blkcpy.blk_pixel_height = area->y2 - area->y1 + 1;
blkcpy.src_pixel_start_height = 0;
blkcpy.src_pixel_start_width = 0;
blkcpy.dst_pixel_start_height = 0;
blkcpy.dst_pixel_start_width = 0;
dma2d_blkcpy(dma2d_dev, &blkcpy);
ret = dma2d_check_status(dma2d_dev);
if (ret)
{
os_printf("DMA2D error during full area copy\n");
}
if(disp_drv->draw_buf->flushing_last)
{
struct msi *msi = (struct msi*)disp_drv->user_data;
struct framebuff *fb;
int count = 0;
disp_flush_rotate_msi_again:
fb = lvgl_osd_msi_get_fb(msi);
if(fb)
{
struct encode_data_s_callback *callback = (struct encode_data_s_callback*)fb->priv;
callback->user_data = (void*)disp_drv;
callback->finish_cb = (osd_finish_cb)lv_disp_flush_ready;
callback->rot_flag = lv_vendor_get_rotate_callback(fb);
fb->data = (void*)p_16;
fb->len = disp_drv->disp_buf_len;
ret = lv_vendor_rotate_callback(disp_drv->ver_res, disp_drv->hor_res);
if (ret) {
msi_delete_fb(msi, fb);
} else {
msi_output_fb(msi, fb);
}
}
//如果其他地方处理慢,要考虑丢帧了
else
{
if(++count%1000 == 0)
{
os_printf("%s drop frame\n",__FUNCTION__);
}
os_sleep_ms(1);
goto disp_flush_rotate_msi_again;
}
}
else
{
lv_disp_flush_ready(disp_drv);
}
}
#endif
#include "lib/lvgl_rotate_rpc/lvgl_rotate_msi.h"
#if LVGL_HW_ROTATE_RPC_EN
#include "lib/heap/av_psram_heap.h"
static void disp_flush_cpu1_hw_rotate_msi(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
lv_color_t *p_16;
p_16 = (lv_color_t*)osd_menu565_buf;
/* CPU1 使用 DMA2D、CPU0 使用 M2M */
if(area->x1 == 0 && area->x2 == disp_drv->hor_res-1)
{
hw_memcpy_no_cache(p_16+area->y1*disp_drv->hor_res,color_p,disp_drv->hor_res*(area->y2-area->y1+1) *sizeof(lv_color_t));
}
else
{
uint32_t y;
for(y = area->y1; y <= area->y2; y++)
{
hw_memcpy_no_cache(p_16+y*disp_drv->hor_res+area->x1,color_p,(area->x2-area->x1+1)*sizeof(lv_color_t));
color_p += (area->x2-area->x1+1);
}
}
if(disp_drv->draw_buf->flushing_last)
{
lvgl_rotate_get_active_buff(p_16);
}
else
{
lv_disp_flush_ready(disp_drv);
}
}
#endif
void lv_port_disp_init_msi(const char *name,uint16_t w,uint16_t h,uint8_t rotate)
{
/*-------------------------
* Initialize your display
* -----------------------*/
disp_init();
static lv_disp_draw_buf_t draw_buf_dsc_1;
/*-----------------------------------
* Register the display in LVGL
*----------------------------------*/
static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
os_memset(&disp_drv, 0, sizeof(lv_disp_drv_t));
lv_color_t *buf_1;
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
//重新配置一下是否旋转,由屏参数配置
if(rotate)
{
disp_drv.sw_rotate = 1;
}
else
{
disp_drv.sw_rotate = 0;
}
disp_drv.rotated = rotate;
//初始化msi
disp_drv.user_data = lvgl_osd_msi(name);
disp_drv.disp_buf_len = w*h*sizeof(lv_color_t);
#if LVGL_HW_ROTATE_RPC_EN
disp_drv.sw_rotate = 0;
disp_drv.rotated = 0;
/*Set up the functions to access to your display*/
/*Set the resolution of the display*/
disp_drv.hor_res = h;
disp_drv.ver_res = w;
disp_drv.full_refresh = 1;
buf_1 = (lv_color_t*)lv_malloc(disp_drv.hor_res*LV_PORT_DISP_LINE*sizeof(lv_color_t));
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, disp_drv.hor_res * LV_PORT_DISP_LINE); /*Initialize the display buffer*/
osd_menu565_buf = (uint8_t *)av_psram_malloc(w*h*2);
sys_dcache_invalid_range((uint32_t)osd_menu565_buf, w*h*2);
disp_drv.flush_cb = disp_flush_cpu1_hw_rotate_msi;
lvgl_rotate_task_init(disp_drv.user_data, lv_disp_flush_ready, (void*)&disp_drv, disp_drv.hor_res, disp_drv.ver_res, LV_COLOR_DEPTH);
#else
#if LVGL_HW_CSC_2_LCD_VIDEO
disp_drv.sw_rotate = 1;
disp_drv.rotated = 0;
/*Set up the functions to access to your display*/
/*Set the resolution of the display*/
disp_drv.hor_res = h;
disp_drv.ver_res = w;
#if (LVGL_HW_CSC_2_LCD_VIDEO == 1)
// 行缓存刷新模式
buf_1 = (lv_color_t*)lv_malloc(disp_drv.hor_res*LV_PORT_DISP_LINE*sizeof(lv_color_t));
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, disp_drv.hor_res * LV_PORT_DISP_LINE); /*Initialize the display buffer*/
osd_menu565_buf = (uint8_t *)av_psram_malloc(w*h*2);
sys_dcache_invalid_range((uint32_t)osd_menu565_buf, w*h*2);
#if DMA2D_EN
disp_drv.flush_cb = disp_flush_rotate_dma2d_msi;
#else
disp_drv.flush_cb = disp_flush_rotate_msi;
#endif
#elif (LVGL_HW_CSC_2_LCD_VIDEO == 2)
// 整帧直接渲染模式
disp_drv.direct_mode = 1;
buf_1 = (lv_color_t*)av_psram_malloc(w*h*sizeof(lv_color_t));
sys_dcache_invalid_range((uint32_t*)buf_1, w*h*sizeof(lv_color_t));
osd_menu565_buf = (uint8_t *)buf_1;
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, w * h); /*Initialize the display buffer*/
disp_drv.flush_cb = disp_flush_msi;
#endif
video_app_csc_msi_init(R_CSC_MSI, CSC_RGB565, CSC_YUV420P, disp_drv.hor_res, disp_drv.ver_res);
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 0);
msi_add_output(NULL, R_CSC_MSI, R_CSC_VIDEO_P2);
#else
//如果旋转,就使用单buf
if(disp_drv.sw_rotate)
{
buf_1 = (lv_color_t*)lv_malloc(w*LV_PORT_DISP_LINE*sizeof(lv_color_t));
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, w * LV_PORT_DISP_LINE); /*Initialize the display buffer*/
//旋转,需要中间层
osd_menu565_buf = (uint8_t *)av_psram_malloc(w*h*2);
sys_dcache_invalid_range((uint32_t*)osd_menu565_buf, w*h*2);
#if DMA2D_EN
disp_drv.flush_cb = disp_flush_rotate_dma2d_msi;
#else
disp_drv.flush_cb = disp_flush_rotate_msi;
#endif
}
else
{
//非旋转,直接绘制就好了
disp_drv.direct_mode = 1;
buf_1 = (lv_color_t*)lv_malloc(w*h*sizeof(lv_color_t));
sys_dcache_invalid_range((uint32_t*)buf_1, w*h*sizeof(lv_color_t));
osd_menu565_buf = (uint8_t *)buf_1;
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, w * h); /*Initialize the display buffer*/
disp_drv.flush_cb = disp_flush_msi;
}
/*Set up the functions to access to your display*/
/*Set the resolution of the display*/
disp_drv.hor_res = w;
disp_drv.ver_res = h;
#endif
#endif
/*Used to copy the buffer's content to the display*/
disp_drv.wait_cb = lv_wait_cb;
/*Set a display buffer*/
disp_drv.draw_buf = &draw_buf_dsc_1;
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
}
#else /*Enable this file at the top*/
/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

View File

@@ -0,0 +1,64 @@
/**
* @file lv_port_disp_templ.h
*
*/
/*Copy this file as "lv_port_disp.h" and set this value to "1" to enable content*/
#if 1
#ifndef LV_PORT_DISP_TEMPL_H
#define LV_PORT_DISP_TEMPL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#define MY_DISP_HOR_RES 240//480 //240
#define MY_DISP_VER_RES 320//854 //320
#define LV_VER_RES_MAX 240
#define LV_COLOR_DEPTH 16
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/* Initialize low level display driver */
void lv_port_disp_init(void *stream,uint16_t w,uint16_t h,uint8_t rotate);
void lv_port_disp_init_msi(const char *name,uint16_t w,uint16_t h,uint8_t rotate);
/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_enable_update(void);
/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_disable_update(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PORT_DISP_TEMPL_H*/
#endif /*Disable/Enable content*/

View File

@@ -0,0 +1,261 @@
/**
* @file lv_port_fs_templ.c
*
*/
/*Copy this file as "lv_port_fs.c" and set this value to "1" to enable content*/
#if 0
/*********************
* INCLUDES
*********************/
#include "lv_port_fs_template.h"
#include "../../lvgl.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void fs_init(void);
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
static lv_fs_res_t fs_size(lv_fs_drv_t * drv, void * file_p, uint32_t * size_p);
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path);
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * rddir_p, char * fn);
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * rddir_p);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_port_fs_init(void)
{
/*----------------------------------------------------
* Initialize your storage device and File System
* -------------------------------------------------*/
fs_init();
/*---------------------------------------------------
* Register the file system interface in LVGL
*--------------------------------------------------*/
/*Add a simple drive to open images*/
static lv_fs_drv_t fs_drv;
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = 'P';
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
fs_drv.write_cb = fs_write;
fs_drv.seek_cb = fs_seek;
fs_drv.tell_cb = fs_tell;
fs_drv.dir_close_cb = fs_dir_close;
fs_drv.dir_open_cb = fs_dir_open;
fs_drv.dir_read_cb = fs_dir_read;
lv_fs_drv_register(&fs_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/*Initialize your Storage device and File system.*/
static void fs_init(void)
{
/*E.g. for FatFS initialize the SD card and FatFS itself*/
/*You code here*/
}
/**
* Open a file
* @param drv pointer to a driver where this function belongs
* @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
* @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
* @return a file descriptor or NULL on error
*/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
{
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
void * f = NULL;
if(mode == LV_FS_MODE_WR) {
/*Open a file for write*/
f = ... /*Add your code here*/
}
else if(mode == LV_FS_MODE_RD) {
/*Open a file for read*/
f = ... /*Add your code here*/
}
else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) {
/*Open a file for read and write*/
f = ... /*Add your code here*/
}
return f;
}
/**
* Close an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable. (opened with fs_open)
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
{
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/*Add your code here*/
return res;
}
/**
* Read data from an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable.
* @param buf pointer to a memory block where to store the read data
* @param btr number of Bytes To Read
* @param br the real number of read bytes (Byte Read)
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/*Add your code here*/
return res;
}
/**
* Write into a file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable
* @param buf pointer to a buffer with the bytes to write
* @param btw Bytes To Write
* @param bw the number of real written bytes (Bytes Written). NULL if unused.
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/*Add your code here*/
return res;
}
/**
* Set the read write pointer. Also expand the file size if necessary.
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable. (opened with fs_open )
* @param pos the new position of read write pointer
* @param whence tells from where to interpret the `pos`. See @lv_fs_whence_t
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
{
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/*Add your code here*/
return res;
}
/**
* Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable.
* @param pos_p pointer to to store the result
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/*Add your code here*/
return res;
}
/**
* Initialize a 'lv_fs_dir_t' variable for directory reading
* @param drv pointer to a driver where this function belongs
* @param path path to a directory
* @return pointer to the directory read descriptor or NULL on error
*/
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
{
void * dir = NULL;
/*Add your code here*/
dir = ... /*Add your code here*/
return dir;
}
/**
* Read the next filename form a directory.
* The name of the directories will begin with '/'
* @param drv pointer to a driver where this function belongs
* @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable
* @param fn pointer to a buffer to store the filename
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * rddir_p, char * fn)
{
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/*Add your code here*/
return res;
}
/**
* Close the directory reading
* @param drv pointer to a driver where this function belongs
* @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * rddir_p)
{
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/*Add your code here*/
return res;
}
#else /*Enable this file at the top*/
/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

View File

@@ -0,0 +1,44 @@
/**
* @file lv_port_fs_templ.h
*
*/
/*Copy this file as "lv_port_fs.h" and set this value to "1" to enable content*/
#if 0
#ifndef LV_PORT_FS_TEMPL_H
#define LV_PORT_FS_TEMPL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lvgl/lvgl.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_port_fs_init(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PORT_FS_TEMPL_H*/
#endif /*Disable/Enable content*/

View File

@@ -0,0 +1,414 @@
/**
* @file lv_port_indev_templ.c
*
*/
/*Copy this file as "lv_port_indev.c" and set this value to "1" to enable content*/
#if 1
/*********************
* INCLUDES
*********************/
#include "lv_port_indev.h"
#include "../../lvgl.h"
#include "lib/touch/touch_pad.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void touchpad_init(void);
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static bool touchpad_is_pressed(void);
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y);
static void mouse_init(void);
static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static bool mouse_is_pressed(void);
static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y);
static void keypad_init(void);
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static uint32_t keypad_get_key(void);
static void encoder_init(void);
static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static void encoder_handler(void);
static void button_init(void);
static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static int8_t button_get_pressed_id(void);
static bool button_is_pressed(uint8_t id);
/**********************
* STATIC VARIABLES
**********************/
lv_indev_t * indev_touchpad;
lv_indev_t * indev_mouse;
lv_indev_t * indev_keypad;
lv_indev_t * indev_encoder;
lv_indev_t * indev_button;
static int32_t encoder_diff;
static lv_indev_state_t encoder_state;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_group_t * group_golop;
void lv_port_indev_init(void)
{
/**
* Here you will find example implementation of input devices supported by LittelvGL:
* - Touchpad
* - Mouse (with cursor support)
* - Keypad (supports GUI usage only with key)
* - Encoder (supports GUI usage only with: left, right, push)
* - Button (external buttons to press points on the screen)
*
* The `..._read()` function are only examples.
* You should shape them according to your hardware
*/
static lv_indev_drv_t indev_drv;
#if 1
/*------------------
* Keypad
* -----------------*/
/*Initialize your keypad or keyboard if you have*/
keypad_init();
/*Register a keypad input device*/
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_KEYPAD;
indev_drv.read_cb = keypad_read;
indev_keypad = lv_indev_drv_register(&indev_drv);
//group_golop = lv_group_create();
//lv_indev_set_group(indev_keypad, group_golop);
/*------------------
* Touchpad
* -----------------*/
static lv_indev_drv_t indev_drv_touchpad;
touchpad_init();
lv_indev_drv_init(&indev_drv_touchpad);
indev_drv_touchpad.type = LV_INDEV_TYPE_POINTER;
indev_drv_touchpad.read_cb = touchpad_read;
indev_touchpad = lv_indev_drv_register(&indev_drv_touchpad);
#else
/*------------------
* Mouse
* -----------------*/
/*Initialize your mouse if you have*/
mouse_init();
/*Register a mouse input device*/
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = mouse_read;
indev_mouse = lv_indev_drv_register(&indev_drv);
/*Set cursor. For simplicity set a HOME symbol now.*/
lv_obj_t * mouse_cursor = lv_img_create(lv_scr_act());
lv_img_set_src(mouse_cursor, LV_SYMBOL_HOME);
lv_indev_set_cursor(indev_mouse, mouse_cursor);
#endif
}
/**********************
* STATIC FUNCTIONS
**********************/
/*------------------
* Touchpad
* -----------------*/
/*Initialize your touchpad*/
static void touchpad_init(void)
{
/*Your code comes here*/
}
/*Will be called by the library to read the touchpad*/
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
static lv_coord_t last_x = 0;
static lv_coord_t last_y = 0;
/*Save the pressed coordinates and the state*/
touch_multipoint_pos_t *touch_point = touch_pad_get_multipoint_xy();
if(touch_point)
{
data->point.x = touch_point->pos_x[0];
data->point.y = touch_point->pos_y[0];
data->state = LV_INDEV_STATE_PR;
touch_pad_free_multipoint_xy(touch_point);
if(last_x == data->point.x && last_y == data->point.y){
data->state = LV_INDEV_STATE_REL;
}
last_x = data->point.x;
last_y = data->point.y;
}
else
{
data->point.x = last_x;
data->point.y = last_y;
data->state = LV_INDEV_STATE_REL;
}
/*Set the last pressed coordinates*/
}
/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{
/*Your code comes here*/
return false;
}
/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
/*Your code comes here*/
}
/*------------------
* Mouse
* -----------------*/
/*Initialize your mouse*/
static void mouse_init(void)
{
/*Your code comes here*/
}
/*Will be called by the library to read the mouse*/
static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
/*Get the current x and y coordinates*/
mouse_get_xy(&data->point.x, &data->point.y);
//printf("x:%d y:%d\r\n",data->point.x,data->point.y);
/*Get whether the mouse button is pressed or released*/
if(mouse_is_pressed()) {
data->state = LV_INDEV_STATE_PR;
}
else {
data->state = LV_INDEV_STATE_REL;
}
}
extern int mouse_x;
extern int mouse_y;
extern int mouse_pass;
/*Return true is the mouse button is pressed*/
static bool mouse_is_pressed(void)
{
/*Your code comes here*/
if(mouse_pass){
return true;
}else
return false;
}
/*Get the x and y coordinates if the mouse is pressed*/
static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y)
{
/*Your code comes here*/
(*x) = mouse_y;//0;
(*y) = 320-mouse_x;//0;
}
/*------------------
* Keypad
* -----------------*/
/*Initialize your keypad*/
static void keypad_init(void)
{
/*Your code comes here*/
}
/*Will be called by the library to read the mouse*/
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
static uint32_t last_key = 0;
/*Get the current x and y coordinates*/
mouse_get_xy(&data->point.x, &data->point.y);
/*Get whether the a key is pressed and save the pressed key*/
uint32_t act_key = keypad_get_key();
if(act_key != 0) {
data->state = LV_INDEV_STATE_PR;
#if 0
/*Translate the keys to LVGL control characters according to your key definitions*/
switch(act_key) {
case 1:
act_key = LV_KEY_NEXT;
break;
case 2:
act_key = LV_KEY_PREV;
break;
case 3:
act_key = LV_KEY_LEFT;
break;
case 4:
act_key = LV_KEY_RIGHT;
break;
case 5:
act_key = LV_KEY_ENTER;
break;
case 6:
act_key = LV_KEY_UP;
break;
case 7:
act_key = LV_KEY_DOWN;
break;
case 8:
act_key = LV_KEY_END;
break;
}
#endif
last_key = act_key;
}
else {
data->state = LV_INDEV_STATE_REL;
}
data->key = last_key;
}
uint32_t key_get_data();
/*Get the currently being pressed key. 0 if no key is pressed*/
static uint32_t keypad_get_key(void)
{
/*Your code comes here*/
/*Your code comes here*/
uint32_t key_ret;
key_ret = key_get_data();
// os_printf("key ret :%d\n",key_ret);
return key_ret;
}
/*------------------
* Encoder
* -----------------*/
/*Initialize your keypad*/
static void encoder_init(void)
{
/*Your code comes here*/
}
/*Will be called by the library to read the encoder*/
static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
data->enc_diff = encoder_diff;
data->state = encoder_state;
}
/*Call this function in an interrupt to process encoder events (turn, press)*/
static void encoder_handler(void)
{
/*Your code comes here*/
encoder_diff += 0;
encoder_state = LV_INDEV_STATE_REL;
}
/*------------------
* Button
* -----------------*/
/*Initialize your buttons*/
static void button_init(void)
{
/*Your code comes here*/
}
/*Will be called by the library to read the button*/
static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
static uint8_t last_btn = 0;
/*Get the pressed button's ID*/
int8_t btn_act = button_get_pressed_id();
if(btn_act >= 0) {
data->state = LV_INDEV_STATE_PR;
last_btn = btn_act;
}
else {
data->state = LV_INDEV_STATE_REL;
}
/*Save the last pressed button's ID*/
data->btn_id = last_btn;
}
/*Get ID (0, 1, 2 ..) of the pressed button*/
static int8_t button_get_pressed_id(void)
{
uint8_t i;
/*Check to buttons see which is being pressed (assume there are 2 buttons)*/
for(i = 0; i < 2; i++) {
/*Return the pressed button's ID*/
if(button_is_pressed(i)) {
return i;
}
}
/*No button pressed*/
return -1;
}
/*Test if `id` button is pressed or not*/
static bool button_is_pressed(uint8_t id)
{
/*Your code comes here*/
return false;
}
#else /*Enable this file at the top*/
/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

View File

@@ -0,0 +1,45 @@
/**
* @file lv_port_indev_templ.h
*
*/
/*Copy this file as "lv_port_indev.h" and set this value to "1" to enable content*/
#if 1
#ifndef LV_PORT_INDEV_TEMPL_H
#define LV_PORT_INDEV_TEMPL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lvgl/lvgl.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_port_indev_init(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PORT_INDEV_TEMPL_H*/
#endif /*Disable/Enable content*/