Skip to content

Commit ac08ec0

Browse files
kisvegaborfacchinm
authored andcommitted
lvgl: add GPU support
1 parent f4b5ab4 commit ac08ec0

File tree

1 file changed

+95
-18
lines changed

1 file changed

+95
-18
lines changed

examples/Portenta_lvgl/Portenta_lvgl.ino

Lines changed: 95 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,124 @@
77
static uint32_t lcd_x_size = 0;
88
static uint32_t lcd_y_size = 0;
99

10-
uint16_t * fb;
10+
static uint16_t * fb;
11+
static lv_disp_drv_t disp_drv;
1112

1213
/* Display flushing */
1314
static void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
1415
{
15-
16-
uint16_t * fb_start = fb + area->y1 * lcd_x_size + area->x1;
1716
uint32_t w = lv_area_get_width(area);
1817
uint32_t h = lv_area_get_height(area);
19-
20-
//GPU: Has artifacts
21-
//stm32_LCD_DrawImage((void*)color_p, (void*)fb_start, w, h, DMA2D_INPUT_RGB565);
2218

19+
#if 1
20+
// SCB_InvalidateICache();
21+
22+
// SCB_CleanInvalidateDCache();
23+
24+
DMA2D_HandleTypeDef * dma2d = stm32_get_DMA2D();
25+
26+
lv_color_t * pDst = (lv_color_t*)fb;
27+
pDst += area->y1 * lcd_x_size + area->x1;
28+
29+
/*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/
30+
dma2d->Init.Mode = DMA2D_M2M;
31+
dma2d->Init.ColorMode = DMA2D_OUTPUT_RGB565;
32+
dma2d->Init.OutputOffset = lcd_x_size - w;
33+
dma2d->Init.AlphaInverted = DMA2D_REGULAR_ALPHA; /* No Output Alpha Inversion*/
34+
dma2d->Init.RedBlueSwap = DMA2D_RB_REGULAR; /* No Output Red & Blue swap */
35+
36+
/*##-2- DMA2D Callbacks Configuration ######################################*/
37+
dma2d->XferCpltCallback = NULL;
38+
39+
/*##-3- Foreground Configuration ###########################################*/
40+
dma2d->LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
41+
dma2d->LayerCfg[1].InputAlpha = 0xFF;
42+
dma2d->LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
43+
dma2d->LayerCfg[1].InputOffset = 0;
44+
dma2d->LayerCfg[1].RedBlueSwap = DMA2D_RB_REGULAR; /* No ForeGround Red/Blue swap */
45+
dma2d->LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA; /* No ForeGround Alpha inversion */
46+
47+
/* DMA2D Initialization */
48+
if(HAL_DMA2D_Init(dma2d) == HAL_OK) {
49+
if(HAL_DMA2D_ConfigLayer(dma2d, 1) == HAL_OK) {
50+
HAL_DMA2D_Start(dma2d, (uint32_t)color_p, (uint32_t)pDst, w, h);
51+
HAL_DMA2D_PollForTransfer(dma2d, 1000);
52+
}
53+
}
54+
#else
2355
//NO GPU
2456
int32_t y;
2557
for(y = area->y1; y <= area->y2; y++) {
2658
memcpy(&fb[y * lcd_x_size + area->x1], color_p, w * sizeof(lv_color_t));
2759
color_p += w;
2860
}
29-
30-
lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
61+
#endif
62+
lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
3163
}
3264

3365

3466
/* If your MCU has hardware accelerator (GPU) then you can use it to blend to memories using opacity
3567
* It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/
3668
static void gpu_blend(lv_disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa)
3769
{
38-
stm32_LCD_DrawImage((void*)src, (void*)dest, length, 1, DMA2D_INPUT_RGB565);
70+
71+
// SCB_CleanInvalidateDCache();
72+
73+
DMA2D_HandleTypeDef * dma2d = stm32_get_DMA2D();
74+
75+
dma2d->Instance = DMA2D;
76+
dma2d->Init.Mode = DMA2D_M2M_BLEND;
77+
dma2d->Init.OutputOffset = 0;
78+
79+
/* Foreground layer */
80+
dma2d->LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
81+
dma2d->LayerCfg[1].InputAlpha = opa;
82+
dma2d->LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
83+
dma2d->LayerCfg[1].InputOffset = 0;
84+
dma2d->LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;
85+
86+
/* Background layer */
87+
dma2d->LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
88+
dma2d->LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
89+
dma2d->LayerCfg[0].InputOffset = 0;
90+
91+
/* DMA2D Initialization */
92+
if (HAL_DMA2D_Init(dma2d) == HAL_OK) {
93+
if (HAL_DMA2D_ConfigLayer(dma2d, 0) == HAL_OK && HAL_DMA2D_ConfigLayer(dma2d, 1) == HAL_OK) {
94+
HAL_DMA2D_BlendingStart(dma2d, (uint32_t) src, (uint32_t) dest, (uint32_t) dest, length, 1);
95+
HAL_DMA2D_PollForTransfer(dma2d, 1000);
96+
}
97+
}
3998
}
4099

41-
/* If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color
42-
* It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/
100+
/* If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color */
43101
static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
44102
const lv_area_t * fill_area, lv_color_t color)
45103
{
46-
uint16_t * fb_start = fb + fill_area->y1 * dest_width + fill_area->x1;
47-
uint32_t w = lv_area_get_width(fill_area);
48-
uint32_t h = lv_area_get_height(fill_area);
49-
// stm32_LCD_FillArea((void*)color_p, (void*)fb_start, w, h, color.full);
104+
// SCB_CleanInvalidateDCache();
105+
106+
DMA2D_HandleTypeDef * dma2d = stm32_get_DMA2D();
107+
108+
109+
lv_color_t * destination = dest_buf + (dest_width * fill_area->y1 + fill_area->x1);
110+
111+
uint32_t w = fill_area->x2 - fill_area->x1 + 1;
112+
dma2d->Instance = DMA2D;
113+
dma2d->Init.Mode = DMA2D_R2M;
114+
dma2d->Init.ColorMode = DMA2D_OUTPUT_RGB565;
115+
dma2d->Init.OutputOffset = dest_width - w;
116+
dma2d->LayerCfg[1].InputAlpha = DMA2D_NO_MODIF_ALPHA;
117+
dma2d->LayerCfg[1].InputColorMode = DMA2D_OUTPUT_RGB565;
118+
119+
/* DMA2D Initialization */
120+
if (HAL_DMA2D_Init(dma2d) == HAL_OK) {
121+
if (HAL_DMA2D_ConfigLayer(dma2d, 1) == HAL_OK) {
122+
lv_coord_t h = lv_area_get_height(fill_area);
123+
if(HAL_DMA2D_BlendingStart(dma2d, lv_color_to32(color), (uint32_t)destination, (uint32_t)destination, w, h) == HAL_OK) {
124+
HAL_DMA2D_PollForTransfer(dma2d, 1000);
125+
}
126+
}
127+
}
50128
}
51129

52130

@@ -92,11 +170,10 @@ void setup() {
92170
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * LV_VER_RES_MAX / 6);
93171

94172
/*Initialize the display*/
95-
lv_disp_drv_t disp_drv;
96173
lv_disp_drv_init(&disp_drv);
97174
disp_drv.flush_cb = my_disp_flush;
98-
// disp_drv.gpu_fill_cb = gpu_fill;
99-
// disp_drv.gpu_blend_cb = gpu_blend;
175+
disp_drv.gpu_fill_cb = gpu_fill;
176+
disp_drv.gpu_blend_cb = gpu_blend;
100177
disp_drv.buffer = &disp_buf;
101178
lv_disp_drv_register(&disp_drv);
102179

0 commit comments

Comments
 (0)