mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-22 23:37:43 +08:00
feat(drivers): add NXP ELCDIF initial display support (#8349)
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Signed-off-by: Felipe Neves <felipe@lvgl.io> Co-authored-by: Attila Kiss <kissattila96@gmail.com> Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
@@ -2077,6 +2077,10 @@ menu "LVGL configuration"
|
||||
bool "Generic MIPI driver"
|
||||
default y if LV_USE_ST7735 || LV_USE_ST7789 || LV_USE_ST7796 || LV_USE_ILI9341
|
||||
|
||||
config LV_USE_NXP_ELCDIF
|
||||
bool "Use NXP ELCDIF to generate display"
|
||||
default n
|
||||
|
||||
config LV_USE_RENESAS_GLCDC
|
||||
bool "Use Renesas GLCDC driver"
|
||||
default n
|
||||
|
||||
@@ -10,6 +10,7 @@ Display
|
||||
gen_mipi
|
||||
ili9341
|
||||
lcd_stm32_guide
|
||||
nxp_elcdif
|
||||
renesas_glcdc
|
||||
st_ltdc
|
||||
st7735
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
.. _nxp_elcdif:
|
||||
|
||||
=============
|
||||
NXP eLCDIF
|
||||
=============
|
||||
|
||||
Overview
|
||||
--------
|
||||
eLCDIF is a peripheral that is provided on some of the NXP devices capable to drive display panels through
|
||||
the RGB interface, it supports different color depths and, on MIPI-DSI capable devices, its output ca be
|
||||
directed to the MIPI display physical interface. The LVGL's NXP eLCDIF driver is responsible to bind the
|
||||
NXP MCUx SDK low-level driver to the LVGL display subsystem.
|
||||
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
- This driver relies on the presence of the MCUx SDK from NXP in the same project
|
||||
- Activate the diver by setting :c:macro:`LV_USE_NXP_ELCDIF` to ``1`` in your *"lv_conf.h"*.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The LVGL driver for eLCDIF assumes the platform already configured the display low-level driver,
|
||||
set the pin-mux, clocks, etc. It also requires the base address of the peripheral and configuration
|
||||
structure already set.
|
||||
|
||||
The following code demonstrates using the diver in :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_DIRECT` mode,
|
||||
please notice in this mode of operation the application is responsible to allocate the framebuffers space
|
||||
and pass them to the display, in the example below `buffer1` and `buffer2` are the current and the next
|
||||
buffers that will be copied to the display screen, being swapped at each flush operation (managed
|
||||
internally by the display driver). Also observe, in direct mode, each buffer should have the space at
|
||||
least to hold at least the size of the screen, that is it, the heigh times the width times the bytes
|
||||
for a pixel (which is application dependent or display supported), on the code below this size is represented
|
||||
by `buf_size`.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
elcdif_rgb_mode_config_t config;
|
||||
ELCDIF_RgbModeGetDefaultConfig(&config);
|
||||
|
||||
lv_display_t * g_disp = lv_nxp_display_elcdif_create_direct(LCDIF, config, buffer1, buffer2, buf_size);
|
||||
lv_display_set_default(g_disp);
|
||||
|
||||
To use the driver in :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_PARTIAL` mode, an extra buffer must be allocated,
|
||||
preferably in the fastest available memory region.
|
||||
|
||||
Buffer swapping can be activated by passing a second buffer of same size instead of the :cpp:expr:`NULL` argument.
|
||||
please notice in this case the `BUF_SIZE` needs to have, at least, space to hold data of 1/10 of the actual
|
||||
display dimensions.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#define BUF_SIZE (DISPLAY_HEIGHT * DISPLAY_WIDTH / 10 * 2) /*1/10 screen size for RGB565 format*/
|
||||
static uint8_t partial_draw_buf[BUF_SIZE];
|
||||
lv_display_t * g_disp = lv_nxp_display_elcdif_create_partial(LCDIF, config, partial_draw_buf, NULL, BUF_SIZE);
|
||||
|
||||
In runtime, the event handler function from the eLCDIF driver should be called inside of the eLCDIF interrupt handler
|
||||
This function is responsible for notify the LVGL display subsystem about a finished flush operation:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void eLCDIF_IRQ_Handler(void)
|
||||
{
|
||||
lv_nxp_display_elcdif_event_handler(g_disp);
|
||||
}
|
||||
@@ -1298,6 +1298,9 @@
|
||||
#define LV_ST_LTDC_USE_DMA2D_FLUSH 0
|
||||
#endif
|
||||
|
||||
/** Driver for NXP ELCDIF */
|
||||
#define LV_USE_NXP_ELCDIF 0
|
||||
|
||||
/** LVGL Windows backend */
|
||||
#define LV_USE_WINDOWS 0
|
||||
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* @file lv_nxp_elcdif.c
|
||||
*
|
||||
* Driver for NXP's ELCD
|
||||
*/
|
||||
|
||||
#include "lv_nxp_elcdif.h"
|
||||
|
||||
#if LV_USE_NXP_ELCDIF == 1
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../display/lv_display_private.h"
|
||||
#include "fsl_video_common.h"
|
||||
#include "fsl_elcdif.h"
|
||||
#include "fsl_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if (defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && (0 != FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET))
|
||||
#define ELCDIF_ADDR_IP_2_CPU(addr) (MEMORY_ConvertMemoryMapAddress((uint32_t)(addr), kMEMORY_DMA2Local))
|
||||
#else
|
||||
#define ELCDIF_ADDR_IP_2_CPU(addr) (addr)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p);
|
||||
static void flush_partial_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p);
|
||||
static lv_color_format_t lv_nxp_elcdif_to_lvgl_color_converter(elcdif_rgb_mode_config_t * config);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_display_t * lv_nxp_display_elcdif_create_direct(LCDIF_Type * base, const elcdif_rgb_mode_config_t * config,
|
||||
void * frame_buffer1,
|
||||
void * frame_buffer2, size_t buf_size)
|
||||
{
|
||||
LV_ASSERT(base);
|
||||
LV_ASSERT(config);
|
||||
|
||||
lv_display_t * disp = lv_display_create(config->panelWidth, config->panelHeight);
|
||||
LV_ASSERT(disp);
|
||||
|
||||
lv_color_format_t color_format = lv_nxp_elcdif_to_lvgl_color_converter((elcdif_rgb_mode_config_t *)config);
|
||||
lv_display_set_color_format(disp, color_format);
|
||||
lv_display_set_buffers(disp, frame_buffer1, frame_buffer2, buf_size, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
lv_display_set_user_data(disp, base);
|
||||
|
||||
ELCDIF_EnableInterrupts(base, kELCDIF_CurFrameDoneInterruptEnable);
|
||||
NVIC_EnableIRQ(eLCDIF_IRQn);
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
lv_display_t * lv_nxp_display_elcdif_create_partial(LCDIF_Type * base, const elcdif_rgb_mode_config_t * config,
|
||||
void * frame_buffer1,
|
||||
void * frame_buffer2, size_t buf_size)
|
||||
{
|
||||
LV_ASSERT(base);
|
||||
LV_ASSERT(config);
|
||||
|
||||
/* Create a direct mode display and then update the buffers to be set in partial mode */
|
||||
lv_display_t * disp = lv_nxp_display_elcdif_create_direct(base, config, frame_buffer1, frame_buffer2, buf_size);
|
||||
ELCDIF_DisableInterrupts(base, kELCDIF_CurFrameDoneInterruptEnable);
|
||||
NVIC_DisableIRQ(eLCDIF_IRQn);
|
||||
|
||||
lv_display_set_flush_cb(disp, flush_partial_cb);
|
||||
lv_display_set_buffers(disp, frame_buffer1, frame_buffer2, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
|
||||
ELCDIF_EnableInterrupts(base, kELCDIF_CurFrameDoneInterruptEnable);
|
||||
NVIC_EnableIRQ(eLCDIF_IRQn);
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
void lv_nxp_display_elcdif_event_handler(const lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) {
|
||||
/* Just return since no valid display has been set yet */
|
||||
return;
|
||||
}
|
||||
|
||||
LCDIF_Type * base = (LCDIF_Type *)lv_display_get_user_data((lv_display_t *)disp);
|
||||
uint32_t intStatus = ELCDIF_GetInterruptStatus(base);
|
||||
|
||||
ELCDIF_ClearInterruptStatus(base, intStatus);
|
||||
|
||||
if(intStatus & kELCDIF_CurFrameDone) {
|
||||
/* flush ready is ISR safe and atomic, so calling inside of the
|
||||
* framebuffer interrupt is safe and makes the flush chain
|
||||
* non blocking even in bare metal systems.
|
||||
*/
|
||||
lv_disp_flush_ready((lv_display_t *)disp);
|
||||
}
|
||||
|
||||
SDK_ISR_EXIT_BARRIER;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p)
|
||||
{
|
||||
LCDIF_Type * base = (LCDIF_Type *)lv_display_get_user_data(disp);
|
||||
|
||||
DCACHE_CleanInvalidateByRange((uint32_t)color_p, lv_display_get_draw_buf_size(disp));
|
||||
|
||||
if(!lv_display_flush_is_last(disp)) {
|
||||
lv_disp_flush_ready(disp);
|
||||
return;
|
||||
}
|
||||
ELCDIF_SetNextBufferAddr(base, (uint32_t)color_p);
|
||||
}
|
||||
|
||||
static void flush_partial_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p)
|
||||
{
|
||||
LCDIF_Type * base = (LCDIF_Type *)lv_display_get_user_data(disp);
|
||||
|
||||
DCACHE_CleanInvalidateByRange((uint32_t)color_p, lv_display_get_draw_buf_size(disp));
|
||||
|
||||
uint8_t * fb = (uint8_t *)ELCDIF_ADDR_IP_2_CPU(base->CUR_BUF);
|
||||
int32_t w = lv_area_get_width(area);
|
||||
int32_t h = lv_area_get_height(area);
|
||||
int32_t disp_w = lv_display_get_horizontal_resolution(disp);
|
||||
int32_t disp_h = lv_display_get_vertical_resolution(disp);
|
||||
int32_t bytes_per_pixel = LV_COLOR_FORMAT_GET_SIZE(lv_display_get_color_format(disp));
|
||||
int32_t i;
|
||||
|
||||
fb = fb + area->y1 * disp_h;
|
||||
fb = fb + area->x1;
|
||||
|
||||
for(i = 0; i < h; i++) {
|
||||
lv_memcpy(fb, color_p, w * bytes_per_pixel);
|
||||
fb += disp_h;
|
||||
color_p += w;
|
||||
}
|
||||
}
|
||||
|
||||
static lv_color_format_t lv_nxp_elcdif_to_lvgl_color_converter(elcdif_rgb_mode_config_t * config)
|
||||
{
|
||||
/*Handle color format conversion*/
|
||||
lv_color_format_t color_format;
|
||||
|
||||
switch(config->pixelFormat) {
|
||||
case kELCDIF_PixelFormatRAW8 :
|
||||
color_format = LV_COLOR_FORMAT_L8;
|
||||
break;
|
||||
case kELCDIF_PixelFormatRGB565 :
|
||||
color_format = LV_COLOR_FORMAT_RGB565;
|
||||
break;
|
||||
case kELCDIF_PixelFormatXRGB8888 :
|
||||
color_format = LV_COLOR_FORMAT_XRGB8888;
|
||||
break;
|
||||
case kELCDIF_PixelFormatRGB888 :
|
||||
color_format = LV_COLOR_FORMAT_RGB888;
|
||||
break;
|
||||
/*
|
||||
There are some color formats in ELCDIF which LVGL does not support.
|
||||
For these, use unknown format and drop a msg for the user
|
||||
*/
|
||||
default :
|
||||
color_format = LV_COLOR_FORMAT_UNKNOWN;
|
||||
LV_LOG_WARN("Not supported color format in ELCDIF. Using LV_UNKNOWN!");
|
||||
}
|
||||
return color_format;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_NXP_ELCDIF*/
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file lv_nxp_elcdif.h
|
||||
* Driver for NXP's ELCD
|
||||
*/
|
||||
|
||||
#ifndef LV_NXP_ELCDIF_DRIVER_H
|
||||
#define LV_NXP_ELCDIF_DRIVER_H
|
||||
|
||||
#include "../../../lvgl.h"
|
||||
#include "../../../display/lv_display.h"
|
||||
|
||||
#if LV_USE_NXP_ELCDIF == 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "fsl_elcdif.h"
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Attach LVGL to ELCDIF using DIRECT rendering mode.
|
||||
* ELCDIF should be already initialized.
|
||||
* @param base The NXP eLCD controller base address
|
||||
* @param config NXP eLCD config object
|
||||
* @param frame_buffer1 pointer the first frame buffers
|
||||
* @param frame_buffer2 pointer the second frame buffers
|
||||
* @param buf_size size of a buffer in bytes (must be at least as large as the screen)
|
||||
* @return a display object initialized and registerd on the LVGL runtime
|
||||
*/
|
||||
lv_display_t * lv_nxp_display_elcdif_create_direct(LCDIF_Type * base, const elcdif_rgb_mode_config_t * config,
|
||||
void * frame_buffer1,
|
||||
void * frame_buffer2, size_t buf_size);
|
||||
|
||||
|
||||
/**
|
||||
* Attach LVGL to ELCDIF using PARTIAL rendering mode.
|
||||
* ELCDIF should be already initialized.
|
||||
* @param base The NXP eLCD controller base address
|
||||
* @param config NXP eLCD config object
|
||||
* @param frame_buffer1 pointer the first frame buffers
|
||||
* @param frame_buffer2 pointer the second frame buffers
|
||||
* @param buf_size size of a buffer in bytes
|
||||
* @return a display object initialized and registerd on the LVGL runtime
|
||||
*/
|
||||
lv_display_t * lv_nxp_display_elcdif_create_partial(LCDIF_Type * base, const elcdif_rgb_mode_config_t * config,
|
||||
void * frame_buffer1,
|
||||
void * frame_buffer2, size_t buf_size);
|
||||
|
||||
/**
|
||||
* Call this function on the LCD Interrupt Service Routine
|
||||
* It tells to LVGL what to do when a framebuffer is transmitted
|
||||
* to the LCD panel
|
||||
* @param disp The display instance that contains the eLCD related data
|
||||
*
|
||||
* @note: the parameter disp is tipycally the return value after
|
||||
* `lv_nxp_display_elcdif_create_direct` has been sucessfully executed
|
||||
*/
|
||||
void lv_nxp_display_elcdif_event_handler(const lv_display_t * disp);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_NXP_ELCDIF*/
|
||||
|
||||
#endif /* LV_NXP_ELCDIF_DRIVER_H */
|
||||
@@ -4209,6 +4209,15 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Driver for NXP ELCDIF */
|
||||
#ifndef LV_USE_NXP_ELCDIF
|
||||
#ifdef CONFIG_LV_USE_NXP_ELCDIF
|
||||
#define LV_USE_NXP_ELCDIF CONFIG_LV_USE_NXP_ELCDIF
|
||||
#else
|
||||
#define LV_USE_NXP_ELCDIF 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** LVGL Windows backend */
|
||||
#ifndef LV_USE_WINDOWS
|
||||
#ifdef CONFIG_LV_USE_WINDOWS
|
||||
|
||||
Reference in New Issue
Block a user