mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
feat(dev): add nuttx lcd driver (#4377)
Signed-off-by: Peter Bee <bijunda1@xiaomi.com>
This commit is contained in:
parent
b78d4dc04b
commit
2cdd41345a
32
Kconfig
32
Kconfig
@ -1220,6 +1220,38 @@ menu "LVGL configuration"
|
||||
depends on LV_USE_LINUX_FBDEV && LV_LINUX_FBDEV_CUSTOM_BUFFER
|
||||
default 60
|
||||
|
||||
config LV_USE_NUTTX_LCD
|
||||
bool "Use NuttX LCD device"
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "NuttX LCD buffer size"
|
||||
depends on LV_USE_NUTTX_LCD
|
||||
default LV_NUTTX_LCD_SINGLE_BUFFER
|
||||
|
||||
config LV_NUTTX_LCD_SINGLE_BUFFER
|
||||
bool "One screen-sized buffer"
|
||||
|
||||
config LV_NUTTX_LCD_DOUBLE_BUFFER
|
||||
bool "Two screen-sized buffer"
|
||||
|
||||
config LV_NUTTX_LCD_CUSTOM_BUFFER
|
||||
bool "Custom-sized buffer"
|
||||
|
||||
endchoice
|
||||
|
||||
config LV_NUTTX_LCD_BUFFER_COUNT
|
||||
int
|
||||
depends on LV_USE_NUTTX_LCD
|
||||
default 0 if LV_NUTTX_LCD_CUSTOM_BUFFER
|
||||
default 1 if LV_NUTTX_LCD_SINGLE_BUFFER
|
||||
default 2 if LV_NUTTX_LCD_DOUBLE_BUFFER
|
||||
|
||||
config LV_NUTTX_LCD_BUFFER_SIZE
|
||||
int "Custom partial buffer size (in number of rows)"
|
||||
depends on LV_USE_NUTTX_LCD && LV_NUTTX_LCD_CUSTOM_BUFFER
|
||||
default 60
|
||||
|
||||
config LV_USE_LINUX_DRM
|
||||
bool "Use Linux DRM device"
|
||||
default n
|
||||
|
@ -726,6 +726,13 @@
|
||||
#define LV_LINUX_FBDEV_BUFFER_SIZE 60
|
||||
#endif
|
||||
|
||||
/*Driver for /dev/lcd*/
|
||||
#define LV_USE_NUTTX_LCD 0
|
||||
#if LV_USE_NUTTX_LCD
|
||||
#define LV_NUTTX_LCD_BUFFER_COUNT 0
|
||||
#define LV_NUTTX_LCD_BUFFER_SIZE 60
|
||||
#endif
|
||||
|
||||
/*Driver for /dev/dri/card*/
|
||||
#define LV_USE_LINUX_DRM 0
|
||||
|
||||
|
1
lvgl.h
1
lvgl.h
@ -115,6 +115,7 @@ extern "C" {
|
||||
|
||||
#include "src/dev/disp/drm/lv_linux_drm.h"
|
||||
#include "src/dev/disp/fb/lv_linux_fbdev.h"
|
||||
#include "src/dev/disp/lcd/lv_nuttx_lcd.h"
|
||||
|
||||
#include "src/dev/input/touchscreen/lv_nuttx_touchscreen.h"
|
||||
|
||||
|
204
src/dev/disp/lcd/lv_nuttx_lcd.c
Normal file
204
src/dev/disp/lcd/lv_nuttx_lcd.c
Normal file
@ -0,0 +1,204 @@
|
||||
/**
|
||||
* @file lv_nuttx_lcd.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_nuttx_lcd.h"
|
||||
#if LV_USE_NUTTX_LCD
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <nuttx/lcd/lcd_dev.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include "../../../lvgl_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
lv_disp_t * disp;
|
||||
struct lcddev_area_s area;
|
||||
struct lcddev_area_align_s align_info;
|
||||
} lv_nuttx_lcd_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static lv_coord_t align_round_up(lv_coord_t v, uint16_t align);
|
||||
static void rounder_cb(lv_event_t * e);
|
||||
static void flush_cb(lv_disp_t * disp, const lv_area_t * area_p,
|
||||
uint8_t * color_p);
|
||||
static lv_disp_t * lcd_init(int fd, int hor_res, int ver_res);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_disp_t * lv_nuttx_lcd_create(const char * dev_path)
|
||||
{
|
||||
struct fb_videoinfo_s vinfo;
|
||||
struct lcd_planeinfo_s pinfo;
|
||||
lv_disp_t * disp;
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
LV_ASSERT_NULL(dev_path);
|
||||
|
||||
LV_LOG_INFO("lcd %s opening", dev_path);
|
||||
fd = open(dev_path, 0);
|
||||
if(fd < 0) {
|
||||
perror("Error: cannot open lcd device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("lcd %s open success", dev_path);
|
||||
|
||||
ret = ioctl(fd, LCDDEVIO_GETVIDEOINFO,
|
||||
(unsigned long)((uintptr_t)&vinfo));
|
||||
if(ret < 0) {
|
||||
perror("Error: ioctl(LCDDEVIO_GETVIDEOINFO) failed");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, LCDDEVIO_GETPLANEINFO,
|
||||
(unsigned long)((uintptr_t)&pinfo));
|
||||
if(ret < 0) {
|
||||
perror("ERROR: ioctl(LCDDEVIO_GETPLANEINFO) failed");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
disp = lcd_init(fd, vinfo.xres, vinfo.yres);
|
||||
if(disp == NULL) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_coord_t align_round_up(lv_coord_t v, uint16_t align)
|
||||
{
|
||||
return (v + align - 1) & ~(align - 1);
|
||||
}
|
||||
|
||||
|
||||
static void rounder_cb(lv_event_t * e)
|
||||
{
|
||||
lv_nuttx_lcd_t * lcd = lv_event_get_user_data(e);
|
||||
lv_area_t * area = lv_event_get_param(e);
|
||||
struct lcddev_area_align_s * align_info = &lcd->align_info;
|
||||
lv_coord_t w;
|
||||
lv_coord_t h;
|
||||
|
||||
area->x1 &= ~(align_info->col_start_align - 1);
|
||||
area->y1 &= ~(align_info->row_start_align - 1);
|
||||
|
||||
w = align_round_up(lv_area_get_width(area), align_info->width_align);
|
||||
h = align_round_up(lv_area_get_height(area), align_info->height_align);
|
||||
|
||||
area->x2 = area->x1 + w - 1;
|
||||
area->y2 = area->y1 + h - 1;
|
||||
}
|
||||
|
||||
static void flush_cb(lv_disp_t * disp, const lv_area_t * area_p,
|
||||
uint8_t * color_p)
|
||||
{
|
||||
lv_nuttx_lcd_t * lcd = disp->user_data;
|
||||
|
||||
lcd->area.row_start = area_p->y1;
|
||||
lcd->area.row_end = area_p->y2;
|
||||
lcd->area.col_start = area_p->x1;
|
||||
lcd->area.col_end = area_p->x2;
|
||||
lcd->area.data = (uint8_t *)color_p;
|
||||
ioctl(lcd->fd, LCDDEVIO_PUTAREA, (unsigned long) & (lcd->area));
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
static lv_disp_t * lcd_init(int fd, int hor_res, int ver_res)
|
||||
{
|
||||
lv_color_t * draw_buf = NULL;
|
||||
lv_color_t * draw_buf_2 = NULL;
|
||||
lv_nuttx_lcd_t * lcd = lv_malloc(sizeof(lv_nuttx_lcd_t));
|
||||
LV_ASSERT_MALLOC(lcd);
|
||||
if(lcd == NULL) {
|
||||
LV_LOG_ERROR("lv_nuttx_lcd_t malloc failed");
|
||||
return NULL;
|
||||
}
|
||||
lv_memzero(lcd, sizeof(lv_nuttx_lcd_t));
|
||||
|
||||
lv_disp_t * disp = lv_disp_create(hor_res, ver_res);
|
||||
if(disp == NULL) {
|
||||
lv_free(lcd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LV_NUTTX_LCD_BUFFER_COUNT > 0
|
||||
uint32_t buf_size = hor_res * ver_res * sizeof(lv_color_t);
|
||||
lv_disp_render_mode_t render_mode = LV_DISP_RENDER_MODE_FULL;
|
||||
#else
|
||||
uint32_t buf_size = hor_res * LV_NUTTX_LCD_BUFFER_SIZE * sizeof(lv_color_t);
|
||||
lv_disp_render_mode_t render_mode = LV_DISP_RENDER_MODE_PARTIAL;
|
||||
#endif
|
||||
|
||||
draw_buf = lv_malloc(buf_size);
|
||||
if(draw_buf == NULL) {
|
||||
LV_LOG_ERROR("display draw_buf malloc failed");
|
||||
lv_free(lcd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LV_NUTTX_LCD_BUFFER_COUNT == 2
|
||||
draw_buf_2 = lv_malloc(buf_size);
|
||||
if(draw_buf_2 == NULL) {
|
||||
LV_LOG_ERROR("display draw_buf_2 malloc failed");
|
||||
lv_free(lcd);
|
||||
lv_free(draw_buf);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
lcd->fd = fd;
|
||||
if(ioctl(fd, LCDDEVIO_GETAREAALIGN, &lcd->align_info) < 0) {
|
||||
perror("Error: ioctl(LCDDEVIO_GETAREAALIGN) failed");
|
||||
}
|
||||
|
||||
lcd->disp = disp;
|
||||
lv_disp_set_draw_buffers(lcd->disp, draw_buf, draw_buf_2, buf_size, render_mode);
|
||||
lv_disp_set_flush_cb(lcd->disp, flush_cb);
|
||||
lv_event_add(&lcd->disp->event_list, rounder_cb, LV_EVENT_INVALIDATE_AREA, lcd);
|
||||
lcd->disp->user_data = lcd;
|
||||
|
||||
return lcd->disp;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_NUTTX_LCD*/
|
45
src/dev/disp/lcd/lv_nuttx_lcd.h
Normal file
45
src/dev/disp/lcd/lv_nuttx_lcd.h
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file lv_nuttx_lcd.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_NUTTX_LCD_H
|
||||
#define LV_NUTTX_LCD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../disp/lv_disp.h"
|
||||
|
||||
#if LV_USE_NUTTX_LCD
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
lv_disp_t * lv_nuttx_lcd_create(const char * dev_path);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_NUTTX_LCD */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LV_NUTTX_LCD_H */
|
@ -2358,6 +2358,31 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Driver for /dev/lcd*/
|
||||
#ifndef LV_USE_NUTTX_LCD
|
||||
#ifdef CONFIG_LV_USE_NUTTX_LCD
|
||||
#define LV_USE_NUTTX_LCD CONFIG_LV_USE_NUTTX_LCD
|
||||
#else
|
||||
#define LV_USE_NUTTX_LCD 0
|
||||
#endif
|
||||
#endif
|
||||
#if LV_USE_NUTTX_LCD
|
||||
#ifndef LV_NUTTX_LCD_BUFFER_COUNT
|
||||
#ifdef CONFIG_LV_NUTTX_LCD_BUFFER_COUNT
|
||||
#define LV_NUTTX_LCD_BUFFER_COUNT CONFIG_LV_NUTTX_LCD_BUFFER_COUNT
|
||||
#else
|
||||
#define LV_NUTTX_LCD_BUFFER_COUNT 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LV_NUTTX_LCD_BUFFER_SIZE
|
||||
#ifdef CONFIG_LV_NUTTX_LCD_BUFFER_SIZE
|
||||
#define LV_NUTTX_LCD_BUFFER_SIZE CONFIG_LV_NUTTX_LCD_BUFFER_SIZE
|
||||
#else
|
||||
#define LV_NUTTX_LCD_BUFFER_SIZE 60
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Driver for /dev/dri/card*/
|
||||
#ifndef LV_USE_LINUX_DRM
|
||||
#ifdef CONFIG_LV_USE_LINUX_DRM
|
||||
|
Loading…
x
Reference in New Issue
Block a user