mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-28 05:26:18 +08:00
feat(display): initial lovyan integration (#8630)
This commit is contained in:
@@ -2075,6 +2075,14 @@ menu "LVGL configuration"
|
|||||||
bool "Use TFT_eSPI driver"
|
bool "Use TFT_eSPI driver"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config LV_USE_LOVYAN_GFX
|
||||||
|
bool "Use LovyanGFX driver"
|
||||||
|
default n
|
||||||
|
config LV_LGFX_USER_INCLUDE
|
||||||
|
string "Header for LovyanGFX user configuration"
|
||||||
|
default "lv_lgfx_user.hpp"
|
||||||
|
depends on LV_USE_LOVYAN_GFX
|
||||||
|
|
||||||
config LV_USE_EVDEV
|
config LV_USE_EVDEV
|
||||||
bool "Use evdev input driver"
|
bool "Use evdev input driver"
|
||||||
default n
|
default n
|
||||||
|
|||||||
@@ -23,9 +23,29 @@ library folder.
|
|||||||
Set up drivers
|
Set up drivers
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
To get started it's recommended to use `TFT_eSPI <https://github.com/Bodmer/TFT_eSPI>`__ library as a TFT
|
To get started, the recommended option is to use the LovyanGFX
|
||||||
driver to simplify testing. To make it work, setup ``TFT_eSPI``
|
library as the TFT driver, since it makes testing much easier.
|
||||||
according to your TFT display type via editing either:
|
You’ll need to create a display configuration file, such as ``my_display.hpp``
|
||||||
|
similar to the example in `LovyanGFX user_setting.ino <https://github.com/lovyan03/LovyanGFX/blob/master/examples/HowToUse/2_user_setting/2_user_setting.ino>`__
|
||||||
|
In the Arduino IDE, you can create a new tab and name it ``my_display.hpp`` and paste the content of your configuration file there.
|
||||||
|
If you prefer not to use LovyanGFX, you can integrate other graphics libraries as well by implementing a wrapper class in the same way LovyanGFX is handled;
|
||||||
|
`lv_lgfx_user.hpp <https://github.com/lvgl/lvgl/blob/master/src/drivers/display/lovyan_gfx/lv_lgfx_user.hpp>`__
|
||||||
|
provides a good example of this. Once your configuration file
|
||||||
|
is ready, update ``lv_conf.h`` to include it, for example:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
/* Interface for Lovyan_GFX */
|
||||||
|
#define LV_USE_LOVYAN_GFX 1
|
||||||
|
|
||||||
|
#if LV_USE_LOVYAN_GFX
|
||||||
|
#define LV_LGFX_USER_INCLUDE "my_display.hpp"
|
||||||
|
#endif /*LV_USE_LOVYAN_GFX*/
|
||||||
|
|
||||||
|
|
||||||
|
Alternatively, you can use `TFT_eSPI <https://github.com/Bodmer/TFT_eSPI>`__ library.
|
||||||
|
To make it work, set up ``TFT_eSPI`` according to your
|
||||||
|
TFT display type via editing either:
|
||||||
|
|
||||||
- ``User_Setup.h``
|
- ``User_Setup.h``
|
||||||
- or by selecting a configuration in the ``User_Setup_Select.h``
|
- or by selecting a configuration in the ``User_Setup_Select.h``
|
||||||
|
|||||||
@@ -1314,6 +1314,14 @@
|
|||||||
/** Interface for TFT_eSPI */
|
/** Interface for TFT_eSPI */
|
||||||
#define LV_USE_TFT_ESPI 0
|
#define LV_USE_TFT_ESPI 0
|
||||||
|
|
||||||
|
/** Interface for Lovyan_GFX */
|
||||||
|
#define LV_USE_LOVYAN_GFX 0
|
||||||
|
|
||||||
|
#if LV_USE_LOVYAN_GFX
|
||||||
|
#define LV_LGFX_USER_INCLUDE "lv_lgfx_user.hpp"
|
||||||
|
|
||||||
|
#endif /*LV_USE_LOVYAN_GFX*/
|
||||||
|
|
||||||
/** Driver for evdev input devices */
|
/** Driver for evdev input devices */
|
||||||
#define LV_USE_EVDEV 0
|
#define LV_USE_EVDEV 0
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if LV_USE_LOVYAN_GFX
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If using LovyanGFX create LGFX class that inherits from lgfx::LGFX_Device
|
||||||
|
* https://github.com/lovyan03/LovyanGFX/blob/master/examples/HowToUse/2_user_setting/2_user_setting.ino */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If using other display drivers that is not LovyanGFX
|
||||||
|
* Create an LGFX wrapper class that implements the functions used in lv_lovyan_gfx.cpp */
|
||||||
|
class LGFX
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LGFX(void) {}
|
||||||
|
|
||||||
|
bool init(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initDMA(void) {}
|
||||||
|
|
||||||
|
void waitDMA(void) {}
|
||||||
|
|
||||||
|
void fillScreen(uint16_t color) {}
|
||||||
|
|
||||||
|
void setRotation(uint8_t rotation) {}
|
||||||
|
|
||||||
|
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) {}
|
||||||
|
|
||||||
|
void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) {}
|
||||||
|
|
||||||
|
void startWrite(void) {}
|
||||||
|
|
||||||
|
uint32_t getStartCount(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void endWrite(void) {}
|
||||||
|
|
||||||
|
void setBrightness(uint8_t brightness){}
|
||||||
|
|
||||||
|
void writePixel(int32_t x, int32_t y, const uint16_t color) {}
|
||||||
|
|
||||||
|
bool getTouch(uint16_t *x, uint16_t *y)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_lovyan_gfx.cpp
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "lv_lovyan_gfx.h"
|
||||||
|
#if LV_USE_LOVYAN_GFX
|
||||||
|
|
||||||
|
#include LV_LGFX_USER_INCLUDE
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
typedef struct {
|
||||||
|
LGFX * tft;
|
||||||
|
} lv_lovyan_gfx_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||||
|
static void resolution_changed_event_cb(lv_event_t * e);
|
||||||
|
static void read_touch(lv_indev_t * indev_driver, lv_indev_data_t * data);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
lv_display_t * lv_lovyan_gfx_create(uint32_t hor_res, uint32_t ver_res, void * buf, uint32_t buf_size_bytes, bool touch)
|
||||||
|
{
|
||||||
|
lv_lovyan_gfx_t * dsc = (lv_lovyan_gfx_t *)lv_malloc_zeroed(sizeof(lv_lovyan_gfx_t));
|
||||||
|
LV_ASSERT_MALLOC(dsc);
|
||||||
|
if(dsc == NULL) return NULL;
|
||||||
|
|
||||||
|
lv_display_t * disp = lv_display_create(hor_res, ver_res);
|
||||||
|
if(disp == NULL) {
|
||||||
|
lv_free(dsc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsc->tft = new LGFX();
|
||||||
|
dsc->tft->init(); /* TFT init */
|
||||||
|
dsc->tft->initDMA();
|
||||||
|
dsc->tft->setRotation(0);
|
||||||
|
dsc->tft->setBrightness(255);
|
||||||
|
dsc->tft->startWrite();
|
||||||
|
dsc->tft->fillScreen(0x00000);
|
||||||
|
|
||||||
|
lv_display_set_driver_data(disp, (void *)dsc);
|
||||||
|
lv_display_set_flush_cb(disp, flush_cb);
|
||||||
|
lv_display_set_color_format(disp, LV_COLOR_FORMAT_RGB565_SWAPPED);
|
||||||
|
lv_display_add_event_cb(disp, resolution_changed_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);
|
||||||
|
lv_display_set_buffers(disp, (void *)buf, NULL, buf_size_bytes, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||||
|
|
||||||
|
if(touch) {
|
||||||
|
/* Register an input device when touch is enabled */
|
||||||
|
lv_indev_t * lv_input = lv_indev_create();
|
||||||
|
lv_indev_set_driver_data(lv_input, (void *)dsc);
|
||||||
|
lv_indev_set_type(lv_input, LV_INDEV_TYPE_POINTER);
|
||||||
|
lv_indev_set_read_cb(lv_input, read_touch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||||
|
{
|
||||||
|
lv_lovyan_gfx_t * dsc = (lv_lovyan_gfx_t *)lv_display_get_driver_data(disp);
|
||||||
|
|
||||||
|
uint32_t w = (area->x2 - area->x1 + 1);
|
||||||
|
uint32_t h = (area->y2 - area->y1 + 1);
|
||||||
|
|
||||||
|
|
||||||
|
if(dsc->tft->getStartCount() == 0) {
|
||||||
|
dsc->tft->endWrite();
|
||||||
|
}
|
||||||
|
dsc->tft->pushImageDMA(area->x1, area->y1, w, h, (uint16_t *)px_map);
|
||||||
|
dsc->tft->waitDMA();
|
||||||
|
|
||||||
|
lv_display_flush_ready(disp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resolution_changed_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_display_t * disp = (lv_display_t *)lv_event_get_target(e);
|
||||||
|
lv_lovyan_gfx_t * dsc = (lv_lovyan_gfx_t *)lv_display_get_driver_data(disp);
|
||||||
|
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
|
||||||
|
int32_t ver_res = lv_display_get_vertical_resolution(disp);
|
||||||
|
lv_display_rotation_t rot = lv_display_get_rotation(disp);
|
||||||
|
|
||||||
|
/* handle rotation */
|
||||||
|
switch(rot) {
|
||||||
|
case LV_DISPLAY_ROTATION_0:
|
||||||
|
dsc->tft->setRotation(0); /* Portrait orientation */
|
||||||
|
break;
|
||||||
|
case LV_DISPLAY_ROTATION_90:
|
||||||
|
dsc->tft->setRotation(1); /* Landscape orientation */
|
||||||
|
break;
|
||||||
|
case LV_DISPLAY_ROTATION_180:
|
||||||
|
dsc->tft->setRotation(2); /* Portrait orientation, flipped */
|
||||||
|
break;
|
||||||
|
case LV_DISPLAY_ROTATION_270:
|
||||||
|
dsc->tft->setRotation(3); /* Landscape orientation, flipped */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_touch(lv_indev_t * indev_driver, lv_indev_data_t * data)
|
||||||
|
{
|
||||||
|
lv_lovyan_gfx_t * dsc = (lv_lovyan_gfx_t *)lv_indev_get_driver_data(indev_driver);
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
bool touched = dsc->tft->getTouch(&x, &y);
|
||||||
|
if(!touched) {
|
||||||
|
data->state = LV_INDEV_STATE_RELEASED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->state = LV_INDEV_STATE_PRESSED;
|
||||||
|
/*Set the coordinates*/
|
||||||
|
data->point.x = x;
|
||||||
|
data->point.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_LOVYAN_GFX*/
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_lovyan_gfx.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_LOVYAN_GFX_H
|
||||||
|
#define LV_LOVYAN_GFX_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "../../../display/lv_display.h"
|
||||||
|
#include "../../../indev/lv_indev.h"
|
||||||
|
|
||||||
|
#if LV_USE_LOVYAN_GFX
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
lv_display_t * lv_lovyan_gfx_create(uint32_t hor_res, uint32_t ver_res, void * buf, uint32_t buf_size_bytes,
|
||||||
|
bool touch);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /* LV_USE_LOVYAN_GFX */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LV_LOVYAN_GFX_H */
|
||||||
@@ -24,6 +24,7 @@ extern "C" {
|
|||||||
#include "display/fb/lv_linux_fbdev.h"
|
#include "display/fb/lv_linux_fbdev.h"
|
||||||
|
|
||||||
#include "display/tft_espi/lv_tft_espi.h"
|
#include "display/tft_espi/lv_tft_espi.h"
|
||||||
|
#include "display/lovyan_gfx/lv_lovyan_gfx.h"
|
||||||
|
|
||||||
#include "display/lcd/lv_lcd_generic_mipi.h"
|
#include "display/lcd/lv_lcd_generic_mipi.h"
|
||||||
#include "display/ili9341/lv_ili9341.h"
|
#include "display/ili9341/lv_ili9341.h"
|
||||||
|
|||||||
@@ -4219,6 +4219,26 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Interface for Lovyan_GFX */
|
||||||
|
#ifndef LV_USE_LOVYAN_GFX
|
||||||
|
#ifdef CONFIG_LV_USE_LOVYAN_GFX
|
||||||
|
#define LV_USE_LOVYAN_GFX CONFIG_LV_USE_LOVYAN_GFX
|
||||||
|
#else
|
||||||
|
#define LV_USE_LOVYAN_GFX 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LV_USE_LOVYAN_GFX
|
||||||
|
#ifndef LV_LGFX_USER_INCLUDE
|
||||||
|
#ifdef CONFIG_LV_LGFX_USER_INCLUDE
|
||||||
|
#define LV_LGFX_USER_INCLUDE CONFIG_LV_LGFX_USER_INCLUDE
|
||||||
|
#else
|
||||||
|
#define LV_LGFX_USER_INCLUDE "lv_lgfx_user.hpp"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_USE_LOVYAN_GFX*/
|
||||||
|
|
||||||
/** Driver for evdev input devices */
|
/** Driver for evdev input devices */
|
||||||
#ifndef LV_USE_EVDEV
|
#ifndef LV_USE_EVDEV
|
||||||
#ifdef CONFIG_LV_USE_EVDEV
|
#ifdef CONFIG_LV_USE_EVDEV
|
||||||
|
|||||||
Reference in New Issue
Block a user