aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2017-10-01 18:00:49 +1000
committerinmarket <andrewh@inmarket.com.au>2017-10-01 18:00:49 +1000
commit82047b1ac6e56361abac0c4b01f06c405e941d19 (patch)
tree85c199ec82a65f0db2e944f309a93b2b7655724f /drivers
parent70222f8c8ddaccf1362f97f4c595d1d06ef680ef (diff)
downloaduGFX-82047b1ac6e56361abac0c4b01f06c405e941d19.tar.gz
uGFX-82047b1ac6e56361abac0c4b01f06c405e941d19.tar.bz2
uGFX-82047b1ac6e56361abac0c4b01f06c405e941d19.zip
STM32LTDC 2nd layer support with alpha
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gdisp/STM32LTDC/board_STM32LTDC_template.h47
-rw-r--r--drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c134
-rw-r--r--drivers/gdisp/STM32LTDC/gdisp_lld_config.h20
3 files changed, 133 insertions, 68 deletions
diff --git a/drivers/gdisp/STM32LTDC/board_STM32LTDC_template.h b/drivers/gdisp/STM32LTDC/board_STM32LTDC_template.h
index 0596fe7b..8164c166 100644
--- a/drivers/gdisp/STM32LTDC/board_STM32LTDC_template.h
+++ b/drivers/gdisp/STM32LTDC/board_STM32LTDC_template.h
@@ -8,6 +8,8 @@
#ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H
+#define ALLOW_2ND_LAYER TRUE
+
static const ltdcConfig driverCfg = {
480, 272, // Width, Height (pixels)
41, 10, // Horizontal, Vertical sync (pixels)
@@ -17,14 +19,14 @@ static const ltdcConfig driverCfg = {
0x000000, // Clear color (RGB888)
{ // Background layer config
- (LLDCOLOR_TYPE *)SDRAM_DEVICE_ADDR, // Frame buffer address
+ (LLDCOLOR_TYPE *)SDRAM_DEVICE_ADDR, // Frame buffer address
480, 272, // Width, Height (pixels)
480 * LTDC_PIXELBYTES, // Line pitch (bytes)
LTDC_PIXELFORMAT, // Pixel format
0, 0, // Start pixel position (x, y)
480, 272, // Size of virtual layer (cx, cy)
- LTDC_COLOR_FUCHSIA, // Default color (ARGB8888)
- 0x980088, // Color key (RGB888)
+ 0x00000000, // Default color (ARGB8888)
+ 0x000000, // Color key (RGB888)
LTDC_BLEND_FIX1_FIX2, // Blending factors
0, // Palette (RGB888, can be NULL)
0, // Palette length
@@ -32,28 +34,47 @@ static const ltdcConfig driverCfg = {
LTDC_LEF_ENABLE // Layer configuration flags
},
- LTDC_UNUSED_LAYER_CONFIG // Foreground layer config
+#if ALLOW_2ND_LAYER
+ { // Foreground layer config (if turned on)
+ (LLDCOLOR_TYPE *)(SDRAM_DEVICE_ADDR+(480 * 272 * LTDC_PIXELBYTES)), // Frame buffer address
+ 480, 272, // Width, Height (pixels)
+ 480 * LTDC_PIXELBYTES, // Line pitch (bytes)
+ LTDC_PIXELFORMAT, // Pixel format
+ 0, 0, // Start pixel position (x, y)
+ 480, 272, // Size of virtual layer (cx, cy)
+ 0x00000000, // Default color (ARGB8888)
+ 0x000000, // Color key (RGB888)
+ LTDC_BLEND_MOD1_MOD2, // Blending factors
+ 0, // Palette (RGB888, can be NULL)
+ 0, // Palette length
+ 0xFF, // Constant alpha factor
+ LTDC_LEF_ENABLE // Layer configuration flags
+ }
+#else
+ LTDC_UNUSED_LAYER_CONFIG
+#endif
};
static GFXINLINE void init_board(GDisplay* g) {
-
- // As we are not using multiple displays we set g->board to NULL as we don't use it.
- g->board = 0;
-
- switch(g->controllerdisplay) {
- case 0: // Set up for Display 0
- // Your init here
- break;
- }
+ // This is function only called once with the display for the background layer.
+ (void)g;
}
static GFXINLINE void post_init_board(GDisplay* g)
{
+ // This is function may be called twice - once for the background display and once
+ // for the foreground display.
+ // Note: It doesn't get called for the foreground display unless gfxconf.h has been
+ // setup for two displays on this controller.
(void)g;
}
static GFXINLINE void set_backlight(GDisplay* g, uint8_t percent)
{
+ // This is function may be called with the display for either the foreground
+ // or the background layer.
+ // Note: It can't be called for the foreground display unless gfxconf.h has been
+ // setup for two displays on this controller.
(void)g;
(void)percent;
}
diff --git a/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c b/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c
index 37fe779f..1dedb22b 100644
--- a/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c
+++ b/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c
@@ -99,13 +99,15 @@ typedef struct ltdcConfig {
/* Driver local routines. */
/*===========================================================================*/
-#define PIXIL_POS(g, x, y) ((y) * driverCfg.bglayer.pitch + (x) * LTDC_PIXELBYTES)
-#define PIXEL_ADDR(g, pos) ((LLDCOLOR_TYPE *)((uint8_t *)driverCfg.bglayer.frame+pos))
+#define PIXIL_POS(g, x, y) ((y) * ((ltdcLayerConfig *)g->priv)->pitch + (x) * LTDC_PIXELBYTES)
+#define PIXEL_ADDR(g, pos) ((LLDCOLOR_TYPE *)((uint8_t *)((ltdcLayerConfig *)g->priv)->frame+pos))
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
+static const ltdcLayerConfig layerOff = LTDC_UNUSED_LAYER_CONFIG;
+
static void _ltdc_reload(void) {
LTDC->SRCR |= LTDC_SRCR_IMR;
while (LTDC->SRCR & (LTDC_SRCR_IMR | LTDC_SRCR_VBR))
@@ -210,7 +212,7 @@ static void _ltdc_init(void) {
_ltdc_layer_init(LTDC_Layer1, &driverCfg.bglayer);
// Load the foreground layer
- _ltdc_layer_init(LTDC_Layer2, &driverCfg.fglayer);
+ _ltdc_layer_init(LTDC_Layer2, &layerOff);
// Interrupt handling
// Possible flags - LTDC_IER_RRIE, LTDC_IER_LIE, LTDC_IER_FUIE, LTDC_IER_TERRIE etc
@@ -227,26 +229,55 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
g->priv = 0;
g->board = 0;
- // Init the board
- init_board(g);
+ switch(g->controllerdisplay) {
+ case 0: // Display 0 is the background layer
+ // Init the board
+ init_board(g);
- // Initialise the LTDC controller
- _ltdc_init();
+ // Initialise the LTDC controller
+ _ltdc_init();
- // Initialise DMA2D
- #if LTDC_USE_DMA2D
- dma2d_init();
- #endif
+ // Initialise DMA2D
+ #if LTDC_USE_DMA2D
+ dma2d_init();
+ #endif
+
+ if (!(driverCfg.bglayer.layerflags & LTDC_LEF_ENABLE))
+ return FALSE;
+
+ g->priv = (void *)&driverCfg.bglayer;
+
+ // Finish Init the board
+ post_init_board(g);
+
+ // Turn on the back-light
+ set_backlight(g, GDISP_INITIAL_BACKLIGHT);
+
+ break;
+
+ case 1: // Display 1 is the foreground layer
+
+ if (!(driverCfg.fglayer.layerflags & LTDC_LEF_ENABLE))
+ return FALSE;
- // Finish Init the board
- post_init_board(g);
+ // Load the foreground layer
+ _ltdc_layer_init(LTDC_Layer2, &driverCfg.fglayer);
+ _ltdc_reload();
- // Turn on the back-light
- set_backlight(g, GDISP_INITIAL_BACKLIGHT);
+ g->priv = (void *)&driverCfg.fglayer;
+
+ // Finish Init the board
+ post_init_board(g);
+
+ break;
+
+ default: // There is only 1 LTDC in the CPU and only the 2 layers in the LTDC.
+ return FALSE;
+ }
// Initialise the GDISP structure
- g->g.Width = driverCfg.bglayer.width;
- g->g.Height = driverCfg.bglayer.height;
+ g->g.Width = ((ltdcLayerConfig *)g->priv)->width;
+ g->g.Height = ((ltdcLayerConfig *)g->priv)->height;
g->g.Orientation = GDISP_ROTATE_0;
g->g.Powermode = powerOn;
g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
@@ -282,7 +313,14 @@ LLDSPEC void gdisp_lld_draw_pixel(GDisplay* g) {
while(DMA2D->CR & DMA2D_CR_START);
#endif
- PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color);
+ #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
+ // As we don't support ARGB pixel types in uGFX yet we will
+ // use RGB with an inverted alpha value for compatibility
+ // ie. 0x00FFFFFF is fully opaque white, 0xFFFFFFFF is fully transparent white
+ PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color) ^ 0xFF000000;
+ #else
+ PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color);
+ #endif
}
LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
@@ -313,27 +351,21 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
while(DMA2D->CR & DMA2D_CR_START);
#endif
- color = PIXEL_ADDR(g, pos)[0];
-
+ #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
+ // As we don't support ARGB pixel types in uGFX yet we will
+ // use RGB with an inverted alpha value for compatibility
+ // ie. 0x00FFFFFF is fully opaque white, 0xFFFFFFFF is fully transparent white
+ color = PIXEL_ADDR(g, pos)[0] ^ 0xFF000000;
+ #else
+ color = PIXEL_ADDR(g, pos)[0];
+ #endif
+
return gdispNative2Color(color);
}
#if GDISP_NEED_CONTROL
LLDSPEC void gdisp_lld_control(GDisplay* g) {
switch(g->p.x) {
- case GDISP_CONTROL_POWER:
- if (g->g.Powermode == (powermode_t)g->p.ptr)
- return;
- switch((powermode_t)g->p.ptr) {
- case powerOff: case powerOn: case powerSleep: case powerDeepSleep:
- // TODO
- break;
- default:
- return;
- }
- g->g.Powermode = (powermode_t)g->p.ptr;
- return;
-
case GDISP_CONTROL_ORIENTATION:
if (g->g.Orientation == (orientation_t)g->p.ptr)
return;
@@ -369,12 +401,6 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
set_backlight(g, (unsigned)g->p.ptr);
g->g.Backlight = (unsigned)g->p.ptr;
return;
-
- case GDISP_CONTROL_CONTRAST:
- if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
- // TODO
- g->g.Contrast = (unsigned)g->p.ptr;
- return;
}
}
#endif
@@ -383,14 +409,14 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
static void dma2d_init(void) {
// Enable DMA2D clock
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_ARGB8888;
#endif
-
+
// Foreground color format
#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
DMA2D->FGPFCCR = FGPFCCR_CM_RGB565;
@@ -401,14 +427,11 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
// Uses p.x,p.y p.cx,p.cy p.color
LLDSPEC void gdisp_lld_fill_area(GDisplay* g)
- {
+ {
uint32_t pos;
uint32_t lineadd;
uint32_t shape;
- // Wait until DMA2D is ready
- while(DMA2D->CR & DMA2D_CR_START);
-
#if GDISP_NEED_CONTROL
switch(g->g.Orientation) {
case GDISP_ROTATE_0:
@@ -438,13 +461,24 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
lineadd = g->g.Width - g->p.cx;
shape = (g->p.cx << 16) | (g->p.cy);
#endif
-
+
+ // Wait until DMA2D is ready
+ while(DMA2D->CR & DMA2D_CR_START);
+
// Start the DMA2D
DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, pos);
DMA2D->OOR = lineadd;
DMA2D->NLR = shape;
- DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color));
- DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START;
+ #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
+ // As we don't support ARGB pixel types in uGFX yet we will
+ // use RGB with an inverted alpha value for compatibility
+ // ie. 0x00FFFFFF is fully opaque white, 0xFFFFFFFF is fully transparent white
+ DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color)) ^ 0xFF000000;
+ #else
+ DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color));
+ #endif
+ ;
+ DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START;
}
/* Oops - the DMA2D only supports GDISP_ROTATE_0.
@@ -464,7 +498,7 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
* access to the framebuffer is fast - probably faster than DMA2D.
* It just uses more CPU.
*/
- #if GDISP_HARDWARE_BITFILLS
+ #if GDISP_HARDWARE_BITFILLS
// 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
@@ -473,7 +507,7 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
// Source setup
DMA2D->FGMAR = LTDC_PIXELBYTES * (g->p.y1 * g->p.x2 + g->p.x1) + (uint32_t)g->p.ptr;
DMA2D->FGOR = g->p.x2 - g->p.cx;
-
+
// Output setup
DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, PIXIL_POS(g, g->p.x, g->p.y));
DMA2D->OOR = g->g.Width - g->p.cx;
diff --git a/drivers/gdisp/STM32LTDC/gdisp_lld_config.h b/drivers/gdisp/STM32LTDC/gdisp_lld_config.h
index 5c3b1883..1476b38b 100644
--- a/drivers/gdisp/STM32LTDC/gdisp_lld_config.h
+++ b/drivers/gdisp/STM32LTDC/gdisp_lld_config.h
@@ -21,8 +21,15 @@
// Both these pixel formats are supported - pick one.
// RGB565 obviously is faster and uses less RAM but with lower color resolution than RGB888
-#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
-//#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
+
+#if defined(GDISP_LTDC_USE_RGB565) && GDISP_LTDC_USE_RGB565
+ #define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+ #if GDISP_TOTAL_DISPLAYS > 1
+ #error "LTDC: You must use RGB888 pixel format with LTDC when using dual layers as only RGB888 currently supports using alpha"
+ #endif
+#else
+ #define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
+#endif
/*===========================================================================*/
@@ -35,9 +42,12 @@
// Accelerated bitfills are also possible but only for GDISP_ROTATE_0
// and if no color translation is required (for now)
- #if !GDISP_NEED_CONTROL && GDISP_PIXELFORMAT == GDISP_LLD_PIXELFORMAT
- #define GDISP_HARDWARE_BITFILLS TRUE
- #endif
+ // Oops - this is not working and adds little performance benefit
+ // so we will just disable it for the near future.
+// #if !GDISP_NEED_CONTROL && !defined(GDISP_PIXELFORMAT)
+// #define GDISP_HARDWARE_BITFILLS TRUE
+// #endif
+
#endif /* GDISP_USE_DMA2D */
#endif /* GFX_USE_GDISP */