diff --git a/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c b/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c index a6a185ee..ebde3345 100644 --- a/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c +++ b/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c @@ -18,12 +18,20 @@ #undef GDISP_SCREEN_WIDTH #endif +#ifndef LTDC_USE_DMA2D + #define LTDC_USE_DMA2D FALSE +#endif + #define GDISP_DRIVER_VMT GDISPVMT_STM32LTDC #include "drivers/gdisp/STM32LTDC/gdisp_lld_config.h" #include "src/gdisp/gdisp_driver.h" #include "stm32_ltdc.h" +#if LTDC_USE_DMA2D + #include "stm32_dma2d.h" +#endif + typedef struct ltdcLayerConfig { // frame LLDCOLOR_TYPE *frame; // Frame buffer address @@ -223,8 +231,9 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) LTDC_Init(); // Initialise DMA2D - //dma2dStart(&DMA2DD1, &dma2d_cfg); - //dma2d_test(); + #if LTDC_USE_DMA2D + dma2d_init(); + #endif // Finish Init the board post_init_board(g); @@ -362,4 +371,87 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) } #endif +#if LTDC_USE_DMA2D + static void dma2d_init(void) + { + // Enable DMA2D clock (DMA2DEN = 1) + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN; + + // Output color format + #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 + DMA2D->OPFCCR = OPFCCR_RGB565; + #elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888 + DMA2D->OPFCCR = OPFCCR_OPFCCR_RGB888; + #endif + + // Foreground color format + #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 + DMA2D->FGPFCCR = FGPFCCR_CM_RGB565; + #elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888 + DMA2D->FGPFCCR = FGPFCCR_CM_RGB888; + #endif + } + + // Uses p.x,p.y p.cx,p.cy p.color + LLDSPEC void gdisp_lld_fill_area(GDisplay* g) + { + LLDCOLOR_TYPE c; + + // Wait until DMA2D is ready + while (1) { + if (!(DMA2D->CR & DMA2D_CR_START)) { + break; + } + } + + c = gdispColor2Native(g->p.color); + + // Output color register + DMA2D->OCOLR = (uint32_t)c; + + // Output memory address register + DMA2D->OMAR = g->p.y * g->g.Width * LTDC_PIXELBYTES + g->p.x * LTDC_PIXELBYTES + (uint32_t)driverCfg.bglayer.frame; + + // Output offset register (in pixels) + DMA2D->OOR = g->g.Width - g->p.cx; + + // PL (pixel per lines to be transferred); NL (number of lines) + DMA2D->NLR = (g->p.cx << 16) | (g->p.cy); + + // Set MODE to R2M and Start the process + DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START; + } + + // Uses p.x,p.y p.cx,p.cy p.x1,p.y1 (=srcx,srcy) p.x2 (=srccx), p.ptr (=buffer) + LLDSPEC void gdisp_lld_blit_area(GDisplay* g) + { + // Wait until DMA2D is ready + while (1) { + if (!(DMA2D->CR & DMA2D_CR_START)) { + break; + } + } + + // Foreground memory address register + DMA2D->FGMAR = g->p.y1 * g->p.x2 * LTDC_PIXELBYTES + g->p.x1 * LTDC_PIXELBYTES + (uint32_t)g->p.ptr; + + // Foreground offset register (expressed in pixels) + DMA2D->FGOR = g->p.x2 - g->p.cx; + + // Output memory address register + DMA2D->OMAR = g->p.y * g->g.Width * LTDC_PIXELBYTES + g->p.x * LTDC_PIXELBYTES + (uint32_t)driverCfg.bglayer.frame; + + // Output offset register (expressed in pixels) + DMA2D->OOR = g->g.Width - g->p.cx; + + // PL (pixel per lines to be transferred); NL (number of lines) + DMA2D->NLR = (g->p.cx << 16) | (g->p.cy); + + // Set MODE to M2M and Start the process + DMA2D->CR = DMA2D_CR_MODE_M2M | DMA2D_CR_START; + } + +#endif /* LTDC_USE_DMA2D */ + + #endif /* GFX_USE_GDISP */ diff --git a/drivers/gdisp/STM32LTDC/gdisp_lld_config.h b/drivers/gdisp/STM32LTDC/gdisp_lld_config.h index 29e016ce..c661f67c 100644 --- a/drivers/gdisp/STM32LTDC/gdisp_lld_config.h +++ b/drivers/gdisp/STM32LTDC/gdisp_lld_config.h @@ -14,11 +14,25 @@ /* Driver hardware support. */ /*===========================================================================*/ +#define LTDC_USE_DMA2D TRUE #define GDISP_HARDWARE_DRAWPIXEL TRUE #define GDISP_HARDWARE_PIXELREAD TRUE #define GDISP_HARDWARE_CONTROL TRUE #define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 + +/*===========================================================================*/ +/* Don't change stuff below this line. Please. */ +/*===========================================================================*/ + +#if LTDC_USE_DMA2D + #define GDISP_HARDWARE_FILLS TRUE + #define GDISP_HARDWARE_BITFILLS TRUE +#else + #define GDISP_HARDWARE_FILLS FALSE + #define GDISP_HARDWARE_BITFILLS FALSE +#endif /* GDISP_USE_DMA2D */ + #endif /* GFX_USE_GDISP */ #endif /* _GDISP_LLD_CONFIG_H */ diff --git a/drivers/gdisp/STM32LTDC/stm32_dma2d.h b/drivers/gdisp/STM32LTDC/stm32_dma2d.h new file mode 100644 index 00000000..d3374d05 --- /dev/null +++ b/drivers/gdisp/STM32LTDC/stm32_dma2d.h @@ -0,0 +1,18 @@ +#ifndef _STM32_DMA2D_H +#define _STM32_DMA2D_H + +#define OPFCCR_ARGB8888 0x00 +#define OPFCCR_RGB888 0x01 +#define OPFCCR_RGB565 0x02 +#define OPFCCR_ARGB1555 0x03 +#define OPFCCR_ARGB4444 0x04 + +#define FGPFCCR_CM_RGB888 0x01 +#define FGPFCCR_CM_RGB565 0x02 + +#define DMA2D_CR_MODE_R2M ((uint32_t)0x00030000) /* Register-to-memory mode */ +#define DMA2D_CR_MODE_M2M ((uint32_t)0x00000000) /* Register-to-memory mode */ + +static void dma2d_init(void); + +#endif /* _STM32_DMA2D_H */