Update LVGL to v9.1.0
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
#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.
|
||||
#warning Please define or replace the macro MY_DISP_VER_RES with the actual screen height, default value 240 is used for now.
|
||||
#define MY_DISP_VER_RES 240
|
||||
#endif
|
||||
|
||||
@@ -34,9 +34,7 @@
|
||||
**********************/
|
||||
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 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 void disp_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -57,78 +55,31 @@ void lv_port_disp_init(void)
|
||||
* -----------------------*/
|
||||
disp_init();
|
||||
|
||||
/*-----------------------------
|
||||
* Create a buffer for drawing
|
||||
*----------------------------*/
|
||||
/*------------------------------------
|
||||
* Create a display and set a flush_cb
|
||||
* -----------------------------------*/
|
||||
lv_display_t * disp = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);
|
||||
lv_display_set_flush_cb(disp, disp_flush);
|
||||
|
||||
/**
|
||||
* 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 1
|
||||
* One buffer for partial rendering*/
|
||||
static lv_color_t buf_1_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
|
||||
lv_display_set_buffers(disp, buf_1_1, NULL, sizeof(buf_1_1), LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
|
||||
/* Example for 1) */
|
||||
static lv_disp_draw_buf_t draw_buf_dsc_1;
|
||||
static lv_color_t buf_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
|
||||
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
|
||||
/* Example 2
|
||||
* Two buffers for partial rendering
|
||||
* In flush_cb DMA or similar hardware should be used to update the display in the background.*/
|
||||
static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10];
|
||||
static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10];
|
||||
lv_display_set_buffers(disp, buf_2_1, buf_2_2, sizeof(buf_2_1), LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
|
||||
/* 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 3
|
||||
* Two buffers screen sized buffer for double buffering.
|
||||
* Both LV_DISPLAY_RENDER_MODE_DIRECT and LV_DISPLAY_RENDER_MODE_FULL works, see their comments*/
|
||||
static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];
|
||||
static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES];
|
||||
lv_display_set_buffers(disp, buf_3_1, buf_3_2, sizeof(buf_3_1), LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
|
||||
/* 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*/
|
||||
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_disp_drv_init(&disp_drv); /*Basic initialization*/
|
||||
|
||||
/*Set up the functions to access to your display*/
|
||||
|
||||
/*Set the resolution of the display*/
|
||||
disp_drv.hor_res = MY_DISP_HOR_RES;
|
||||
disp_drv.ver_res = MY_DISP_VER_RES;
|
||||
|
||||
/*Used to copy the buffer's content to the display*/
|
||||
disp_drv.flush_cb = disp_flush;
|
||||
|
||||
/*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);
|
||||
}
|
||||
|
||||
/**********************
|
||||
@@ -157,10 +108,11 @@ void disp_disable_update(void)
|
||||
disp_flush_enabled = false;
|
||||
}
|
||||
|
||||
/*Flush the content of the internal buffer the specific area on the display
|
||||
/*Flush the content of the internal buffer the specific area on the display.
|
||||
*`px_map` contains the rendered image as raw pixel map and it should be copied to `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.*/
|
||||
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
|
||||
*'lv_display_flush_ready()' has to be called when it's finished.*/
|
||||
static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)
|
||||
{
|
||||
if(disp_flush_enabled) {
|
||||
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
|
||||
@@ -170,36 +122,17 @@ static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_colo
|
||||
for(y = area->y1; y <= area->y2; y++) {
|
||||
for(x = area->x1; x <= area->x2; x++) {
|
||||
/*Put a pixel to the display. For example:*/
|
||||
/*put_px(x, y, *color_p)*/
|
||||
color_p++;
|
||||
/*put_px(x, y, *px_map)*/
|
||||
px_map++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*IMPORTANT!!!
|
||||
*Inform the graphics library that you are ready with the flushing*/
|
||||
lv_disp_flush_ready(disp_drv);
|
||||
lv_display_flush_ready(disp_drv);
|
||||
}
|
||||
|
||||
/*OPTIONAL: GPU INTERFACE*/
|
||||
|
||||
/*If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color*/
|
||||
//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)
|
||||
//{
|
||||
// /*It's an example code which should be done by your GPU*/
|
||||
// int32_t x, y;
|
||||
// dest_buf += dest_width * fill_area->y1; /*Go to the first line*/
|
||||
//
|
||||
// for(y = fill_area->y1; y <= fill_area->y2; y++) {
|
||||
// for(x = fill_area->x1; x <= fill_area->x2; x++) {
|
||||
// dest_buf[x] = color;
|
||||
// }
|
||||
// dest_buf+=dest_width; /*Go to the next line*/
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
#else /*Enable this file at the top*/
|
||||
|
||||
/*This dummy typedef exists purely to silence -Wpedantic.*/
|
||||
|
||||
@@ -34,7 +34,7 @@ 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_read(lv_fs_drv_t * drv, void * rddir_p, char * fn, uint32_t fn_len);
|
||||
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * rddir_p);
|
||||
|
||||
/**********************
|
||||
@@ -64,7 +64,6 @@ void lv_port_fs_init(void)
|
||||
* 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);
|
||||
|
||||
@@ -195,8 +194,8 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs
|
||||
/**
|
||||
* 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
|
||||
* @param file_p pointer to a file_t variable
|
||||
* @param pos_p pointer 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)
|
||||
@@ -228,9 +227,10 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
|
||||
* @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
|
||||
* @param fn_len length of the 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)
|
||||
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * rddir_p, char * fn, uint32_t fn_len)
|
||||
{
|
||||
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_port_indev_template.h"
|
||||
#include "../../lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -25,25 +24,25 @@
|
||||
**********************/
|
||||
|
||||
static void touchpad_init(void);
|
||||
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
|
||||
static void touchpad_read(lv_indev_t * indev, 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 touchpad_get_xy(int32_t * x, int32_t * y);
|
||||
|
||||
static void mouse_init(void);
|
||||
static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
|
||||
static void mouse_read(lv_indev_t * indev, 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 mouse_get_xy(int32_t * x, int32_t * y);
|
||||
|
||||
static void keypad_init(void);
|
||||
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
|
||||
static void keypad_read(lv_indev_t * indev, 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_read(lv_indev_t * indev, 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 void button_read(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
static int8_t button_get_pressed_id(void);
|
||||
static bool button_is_pressed(uint8_t id);
|
||||
|
||||
@@ -81,8 +80,6 @@ void lv_port_indev_init(void)
|
||||
* You should shape them according to your hardware
|
||||
*/
|
||||
|
||||
static lv_indev_drv_t indev_drv;
|
||||
|
||||
/*------------------
|
||||
* Touchpad
|
||||
* -----------------*/
|
||||
@@ -91,10 +88,9 @@ void lv_port_indev_init(void)
|
||||
touchpad_init();
|
||||
|
||||
/*Register a touchpad input device*/
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = touchpad_read;
|
||||
indev_touchpad = lv_indev_drv_register(&indev_drv);
|
||||
indev_touchpad = lv_indev_create();
|
||||
lv_indev_set_type(indev_touchpad, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(indev_touchpad, touchpad_read);
|
||||
|
||||
/*------------------
|
||||
* Mouse
|
||||
@@ -104,14 +100,13 @@ void lv_port_indev_init(void)
|
||||
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);
|
||||
indev_mouse = lv_indev_create();
|
||||
lv_indev_set_type(indev_mouse, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(indev_mouse, mouse_read);
|
||||
|
||||
/*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_obj_t * mouse_cursor = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(mouse_cursor, LV_SYMBOL_HOME);
|
||||
lv_indev_set_cursor(indev_mouse, mouse_cursor);
|
||||
|
||||
/*------------------
|
||||
@@ -122,10 +117,9 @@ void lv_port_indev_init(void)
|
||||
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);
|
||||
indev_keypad = lv_indev_create();
|
||||
lv_indev_set_type(indev_keypad, LV_INDEV_TYPE_KEYPAD);
|
||||
lv_indev_set_read_cb(indev_keypad, keypad_read);
|
||||
|
||||
/*Later you should create group(s) with `lv_group_t * group = lv_group_create()`,
|
||||
*add objects to the group with `lv_group_add_obj(group, obj)`
|
||||
@@ -140,10 +134,9 @@ void lv_port_indev_init(void)
|
||||
encoder_init();
|
||||
|
||||
/*Register a encoder input device*/
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_ENCODER;
|
||||
indev_drv.read_cb = encoder_read;
|
||||
indev_encoder = lv_indev_drv_register(&indev_drv);
|
||||
indev_encoder = lv_indev_create();
|
||||
lv_indev_set_type(indev_encoder, LV_INDEV_TYPE_ENCODER);
|
||||
lv_indev_set_read_cb(indev_touchpad, encoder_read);
|
||||
|
||||
/*Later you should create group(s) with `lv_group_t * group = lv_group_create()`,
|
||||
*add objects to the group with `lv_group_add_obj(group, obj)`
|
||||
@@ -158,10 +151,9 @@ void lv_port_indev_init(void)
|
||||
button_init();
|
||||
|
||||
/*Register a button input device*/
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_BUTTON;
|
||||
indev_drv.read_cb = button_read;
|
||||
indev_button = lv_indev_drv_register(&indev_drv);
|
||||
indev_button = lv_indev_create();
|
||||
lv_indev_set_type(indev_button, LV_INDEV_TYPE_BUTTON);
|
||||
lv_indev_set_read_cb(indev_button, button_read);
|
||||
|
||||
/*Assign buttons to points on the screen*/
|
||||
static const lv_point_t btn_points[2] = {
|
||||
@@ -186,10 +178,10 @@ static void touchpad_init(void)
|
||||
}
|
||||
|
||||
/*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 void touchpad_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
|
||||
{
|
||||
static lv_coord_t last_x = 0;
|
||||
static lv_coord_t last_y = 0;
|
||||
static int32_t last_x = 0;
|
||||
static int32_t last_y = 0;
|
||||
|
||||
/*Save the pressed coordinates and the state*/
|
||||
if(touchpad_is_pressed()) {
|
||||
@@ -214,7 +206,7 @@ static bool touchpad_is_pressed(void)
|
||||
}
|
||||
|
||||
/*Get the x and y coordinates if the touchpad is pressed*/
|
||||
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
|
||||
static void touchpad_get_xy(int32_t * x, int32_t * y)
|
||||
{
|
||||
/*Your code comes here*/
|
||||
|
||||
@@ -233,7 +225,7 @@ static void mouse_init(void)
|
||||
}
|
||||
|
||||
/*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)
|
||||
static void mouse_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
|
||||
{
|
||||
/*Get the current x and y coordinates*/
|
||||
mouse_get_xy(&data->point.x, &data->point.y);
|
||||
@@ -256,7 +248,7 @@ static bool mouse_is_pressed(void)
|
||||
}
|
||||
|
||||
/*Get the x and y coordinates if the mouse is pressed*/
|
||||
static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y)
|
||||
static void mouse_get_xy(int32_t * x, int32_t * y)
|
||||
{
|
||||
/*Your code comes here*/
|
||||
|
||||
@@ -275,7 +267,7 @@ static void keypad_init(void)
|
||||
}
|
||||
|
||||
/*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 void keypad_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
|
||||
{
|
||||
static uint32_t last_key = 0;
|
||||
|
||||
@@ -327,14 +319,14 @@ static uint32_t keypad_get_key(void)
|
||||
* Encoder
|
||||
* -----------------*/
|
||||
|
||||
/*Initialize your keypad*/
|
||||
/*Initialize your encoder*/
|
||||
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)
|
||||
static void encoder_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
|
||||
{
|
||||
|
||||
data->enc_diff = encoder_diff;
|
||||
@@ -361,7 +353,7 @@ static void button_init(void)
|
||||
}
|
||||
|
||||
/*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 void button_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
|
||||
{
|
||||
|
||||
static uint8_t last_btn = 0;
|
||||
|
||||
@@ -17,7 +17,11 @@ extern "C" {
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* @file lv_port_lcd_stm32_template.c
|
||||
*
|
||||
* Example implementation of the LVGL LCD display drivers on the STM32 platform
|
||||
*/
|
||||
|
||||
/*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
|
||||
#if 0
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
/* Include STM32Cube files here, e.g.:
|
||||
#include "stm32f7xx_hal.h"
|
||||
*/
|
||||
|
||||
#include "lv_port_disp.h"
|
||||
#include "./src/drivers/display/st7789/lv_st7789.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#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_VER_RES with the actual screen height, default value 240 is used for now.
|
||||
#define MY_DISP_VER_RES 240
|
||||
#endif
|
||||
|
||||
#define BUS_SPI1_POLL_TIMEOUT 0x1000U
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lcd_color_transfer_ready_cb(SPI_HandleTypeDef * hspi);
|
||||
static int32_t lcd_io_init(void);
|
||||
static void lcd_send_cmd(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, const uint8_t * param,
|
||||
size_t param_size);
|
||||
static void lcd_send_color(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, uint8_t * param,
|
||||
size_t param_size);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_display_t * lcd_disp;
|
||||
static volatile int lcd_bus_busy = 0;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_port_display_init(void)
|
||||
{
|
||||
/* Initialize LCD I/O */
|
||||
if(lcd_io_init() != 0)
|
||||
return;
|
||||
|
||||
/* Create the LVGL display object and the ST7789 LCD display driver */
|
||||
lcd_disp = lv_st7789_create(MY_DISP_HOR_RES, MY_DISP_VER_RES, LV_LCD_FLAG_NONE, lcd_send_cmd, lcd_send_color);
|
||||
lv_display_set_rotation(lcd_disp, LV_DISPLAY_ROTATION_270); /* set landscape orientation */
|
||||
|
||||
/* Example: two dynamically allocated buffers for partial rendering */
|
||||
lv_color_t * buf1 = NULL;
|
||||
lv_color_t * buf2 = NULL;
|
||||
|
||||
uint32_t buf_size = MY_DISP_HOR_RES * MY_DISP_VER_RES / 10 * lv_color_format_get_size(lv_display_get_color_format(
|
||||
lcd_disp));
|
||||
|
||||
buf1 = lv_malloc(buf_size);
|
||||
if(buf1 == NULL) {
|
||||
LV_LOG_ERROR("display draw buffer malloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
buf2 = lv_malloc(buf_size);
|
||||
if(buf2 == NULL) {
|
||||
LV_LOG_ERROR("display buffer malloc failed");
|
||||
lv_free(buf1);
|
||||
return;
|
||||
}
|
||||
lv_display_set_buffers(lcd_disp, buf1, buf2, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/* Callback is called when background transfer finished */
|
||||
static void lcd_color_transfer_ready_cb(SPI_HandleTypeDef * hspi)
|
||||
{
|
||||
/* CS high */
|
||||
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
|
||||
lcd_bus_busy = 0;
|
||||
lv_display_flush_ready(lcd_disp);
|
||||
}
|
||||
|
||||
/* Initialize LCD I/O bus, reset LCD */
|
||||
static int32_t lcd_io_init(void)
|
||||
{
|
||||
/* Register SPI Tx Complete Callback */
|
||||
HAL_SPI_RegisterCallback(&hspi1, HAL_SPI_TX_COMPLETE_CB_ID, lcd_color_transfer_ready_cb);
|
||||
|
||||
/* reset LCD */
|
||||
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_RESET);
|
||||
HAL_Delay(100);
|
||||
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_SET);
|
||||
HAL_Delay(100);
|
||||
|
||||
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/* Platform-specific implementation of the LCD send command function. In general this should use polling transfer. */
|
||||
static void lcd_send_cmd(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, const uint8_t * param,
|
||||
size_t param_size)
|
||||
{
|
||||
LV_UNUSED(disp);
|
||||
while(lcd_bus_busy); /* wait until previous transfer is finished */
|
||||
/* Set the SPI in 8-bit mode */
|
||||
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
HAL_SPI_Init(&hspi1);
|
||||
/* DCX low (command) */
|
||||
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);
|
||||
/* CS low */
|
||||
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
|
||||
/* send command */
|
||||
if(HAL_SPI_Transmit(&hspi1, cmd, cmd_size, BUS_SPI1_POLL_TIMEOUT) == HAL_OK) {
|
||||
/* DCX high (data) */
|
||||
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
|
||||
/* for short data blocks we use polling transfer */
|
||||
HAL_SPI_Transmit(&hspi1, (uint8_t *)param, (uint16_t)param_size, BUS_SPI1_POLL_TIMEOUT);
|
||||
/* CS high */
|
||||
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
}
|
||||
|
||||
/* Platform-specific implementation of the LCD send color function. For better performance this should use DMA transfer.
|
||||
* In case of a DMA transfer a callback must be installed to notify LVGL about the end of the transfer.
|
||||
*/
|
||||
static void lcd_send_color(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, uint8_t * param,
|
||||
size_t param_size)
|
||||
{
|
||||
LV_UNUSED(disp);
|
||||
while(lcd_bus_busy); /* wait until previous transfer is finished */
|
||||
/* Set the SPI in 8-bit mode */
|
||||
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
HAL_SPI_Init(&hspi1);
|
||||
/* DCX low (command) */
|
||||
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);
|
||||
/* CS low */
|
||||
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
|
||||
/* send command */
|
||||
if(HAL_SPI_Transmit(&hspi1, cmd, cmd_size, BUS_SPI1_POLL_TIMEOUT) == HAL_OK) {
|
||||
/* DCX high (data) */
|
||||
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
|
||||
/* for color data use DMA transfer */
|
||||
/* Set the SPI in 16-bit mode to match endianess */
|
||||
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
|
||||
HAL_SPI_Init(&hspi1);
|
||||
lcd_bus_busy = 1;
|
||||
HAL_SPI_Transmit_DMA(&hspi1, param, (uint16_t)param_size / 2);
|
||||
/* NOTE: CS will be reset in the transfer ready callback */
|
||||
}
|
||||
}
|
||||
|
||||
#else /*Enable this file at the top*/
|
||||
|
||||
/*This dummy typedef exists purely to silence -Wpedantic.*/
|
||||
typedef int keep_pedantic_happy;
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file lv_port_lcd_stm32_template.h
|
||||
*
|
||||
*/
|
||||
|
||||
/*Copy this file as "lv_port_disp.h" and set this value to "1" to enable content*/
|
||||
#if 0
|
||||
|
||||
#ifndef LV_PORT_LCD_STM32_TEMPL_H
|
||||
#define LV_PORT_LCD_STM32_TEMPL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
/* Initialize low level display driver */
|
||||
void lv_port_disp_init(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_PORT_LCD_STM32_TEMPL_H*/
|
||||
|
||||
#endif /*Disable/Enable content*/
|
||||
Reference in New Issue
Block a user