From 82047b1ac6e56361abac0c4b01f06c405e941d19 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sun, 1 Oct 2017 18:00:49 +1000 Subject: [PATCH] STM32LTDC 2nd layer support with alpha --- .../STM32F429i-Discovery/board_STM32LTDC.h | 80 +++++---- .../STM32F439i-Eval/CubeHal/board_STM32LTDC.h | 75 +++++---- .../STM32F469i-Discovery/board_STM32LTDC.h | 92 ++++++----- .../STM32F746-Discovery/board_STM32LTDC.h | 153 +++++++++--------- changelog.txt | 9 ++ .../modules/gdisp/multiple_displays/gfxconf.h | 2 +- .../STM32LTDC/board_STM32LTDC_template.h | 47 ++++-- drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c | 134 +++++++++------ drivers/gdisp/STM32LTDC/gdisp_lld_config.h | 20 ++- src/gdisp/gdisp_colors.h | 7 + 10 files changed, 375 insertions(+), 244 deletions(-) diff --git a/boards/base/STM32F429i-Discovery/board_STM32LTDC.h b/boards/base/STM32F429i-Discovery/board_STM32LTDC.h index 8cd3048d..2f125c5c 100644 --- a/boards/base/STM32F429i-Discovery/board_STM32LTDC.h +++ b/boards/base/STM32F429i-Discovery/board_STM32LTDC.h @@ -23,6 +23,8 @@ static const SPIConfig spi_cfg = { ((1 << 3) & SPI_CR1_BR) | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR }; +#define ALLOW_2ND_LAYER TRUE + static const ltdcConfig driverCfg = { 240, 320, 10, 2, @@ -37,15 +39,33 @@ static const ltdcConfig driverCfg = { LTDC_PIXELFORMAT, // fmt 0, 0, // x, y 240, 320, // cx, cy - LTDC_COLOR_FUCHSIA, // defcolor - 0x980088, // keycolor + 0x00000000, // defcolor + 0x000000, // keycolor LTDC_BLEND_FIX1_FIX2, // blending 0, // palette 0, // palettelen 0xFF, // alpha LTDC_LEF_ENABLE // flags }, +#if ALLOW_2ND_LAYER + { // Foreground layer config (if turned on) + (LLDCOLOR_TYPE *)(SDRAM_DEVICE_ADDR+(240 * 320 * LTDC_PIXELBYTES)), // Frame buffer address + 240, 320, // width, height + 240 * LTDC_PIXELBYTES, // pitch + LTDC_PIXELFORMAT, // fmt + 0, 0, // x, y + 240, 320, // 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 }; #include "ili9341.h" @@ -146,45 +166,39 @@ static void Init9341(GDisplay *g) { } static void init_board(GDisplay *g) { + (void) g; - // As we are not using multiple displays we set g->board to NULL as we don't use it. - g->board = 0; + palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7)); // UART_TX + palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7)); // UART_RX + palSetPadMode(GPIOF, GPIOF_LCD_DCX, PAL_MODE_ALTERNATE(5)); + palSetPadMode(GPIOF, GPIOF_LCD_DE, PAL_MODE_ALTERNATE(14)); - switch(g->controllerdisplay) { - case 0: // Set up for Display 0 - palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7)); // UART_TX - palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7)); // UART_RX - palSetPadMode(GPIOF, GPIOF_LCD_DCX, PAL_MODE_ALTERNATE(5)); - palSetPadMode(GPIOF, GPIOF_LCD_DE, PAL_MODE_ALTERNATE(14)); + #define STM32_SAISRC_NOCLOCK (0 << 23) /**< No clock. */ + #define STM32_SAISRC_PLL (1 << 23) /**< SAI_CKIN is PLL. */ + #define STM32_SAIR_DIV2 (0 << 16) /**< R divided by 2. */ + #define STM32_SAIR_DIV4 (1 << 16) /**< R divided by 4. */ + #define STM32_SAIR_DIV8 (2 << 16) /**< R divided by 8. */ + #define STM32_SAIR_DIV16 (3 << 16) /**< R divided by 16. */ - #define STM32_SAISRC_NOCLOCK (0 << 23) /**< No clock. */ - #define STM32_SAISRC_PLL (1 << 23) /**< SAI_CKIN is PLL. */ - #define STM32_SAIR_DIV2 (0 << 16) /**< R divided by 2. */ - #define STM32_SAIR_DIV4 (1 << 16) /**< R divided by 4. */ - #define STM32_SAIR_DIV8 (2 << 16) /**< R divided by 8. */ - #define STM32_SAIR_DIV16 (3 << 16) /**< R divided by 16. */ + #define STM32_PLLSAIN_VALUE 192 + #define STM32_PLLSAIQ_VALUE 7 + #define STM32_PLLSAIR_VALUE 4 + #define STM32_PLLSAIR_POST STM32_SAIR_DIV4 - #define STM32_PLLSAIN_VALUE 192 - #define STM32_PLLSAIQ_VALUE 7 - #define STM32_PLLSAIR_VALUE 4 - #define STM32_PLLSAIR_POST STM32_SAIR_DIV4 + /* PLLSAI activation.*/ + RCC->PLLSAICFGR = (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24); + RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | STM32_PLLSAIR_POST; + RCC->CR |= RCC_CR_PLLSAION; - /* PLLSAI activation.*/ - RCC->PLLSAICFGR = (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24); - RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | STM32_PLLSAIR_POST; - RCC->CR |= RCC_CR_PLLSAION; + // Initialise the SDRAM + SDRAM_Init(); - // Initialise the SDRAM - SDRAM_Init(); + // Clear the SDRAM + memset((void *)SDRAM_BANK_ADDR, 0, 0x400000); - // Clear the SDRAM - memset((void *)SDRAM_BANK_ADDR, 0, 0x400000); + spiStart(SPI_PORT, &spi_cfg); - spiStart(SPI_PORT, &spi_cfg); - - Init9341(g); - break; - } + Init9341(g); } static GFXINLINE void post_init_board(GDisplay *g) { diff --git a/boards/base/STM32F439i-Eval/CubeHal/board_STM32LTDC.h b/boards/base/STM32F439i-Eval/CubeHal/board_STM32LTDC.h index 2faa8550..fd9a32ca 100644 --- a/boards/base/STM32F439i-Eval/CubeHal/board_STM32LTDC.h +++ b/boards/base/STM32F439i-Eval/CubeHal/board_STM32LTDC.h @@ -17,6 +17,8 @@ #include "stm32f4xx_hal.h" #include "stm324x9i_eval_sdram.h" +#define ALLOW_2ND_LAYER TRUE + // Panel parameters // This panel is a AMPIRE640480 panel. @@ -35,8 +37,8 @@ static const ltdcConfig driverCfg = { LTDC_PIXELFORMAT, // Pixel format 0, 0, // Start pixel position (x, y) 640, 480, // 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 @@ -44,7 +46,25 @@ 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+(640 * 480 * LTDC_PIXELBYTES)), // Frame buffer address + 640, 480, // Width, Height (pixels) + 640 * LTDC_PIXELBYTES, // Line pitch (bytes) + LTDC_PIXELFORMAT, // Pixel format + 0, 0, // Start pixel position (x, y) + 640, 480, // 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 }; // LCD Clock values @@ -56,10 +76,10 @@ static void configureLcdClock(void) { #if 1 RCC_PeriphCLKInitTypeDef periph_clk_init_struct; - + periph_clk_init_struct.PLLSAI.PLLSAIN = LCD_PLLSAIN_VALUE; - periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; - periph_clk_init_struct.PLLSAI.PLLSAIR = LCD_PLLSAIR_VALUE; + periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; + periph_clk_init_struct.PLLSAI.PLLSAIR = LCD_PLLSAIR_VALUE; periph_clk_init_struct.PLLSAIDivR = LCD_PLLSAIDIVR_VALUE; HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct); #else @@ -77,59 +97,52 @@ static void configureLcdPins(void) GPIO_InitTypeDef GPIO_Init_Structure; // Enable peripheral clocks - __GPIOI_CLK_ENABLE(); + __GPIOI_CLK_ENABLE(); __GPIOJ_CLK_ENABLE(); - __GPIOK_CLK_ENABLE(); + __GPIOK_CLK_ENABLE(); /*** LTDC Pins configuration ***/ // GPIOI - GPIO_Init_Structure.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; + GPIO_Init_Structure.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; GPIO_Init_Structure.Mode = GPIO_MODE_AF_PP; GPIO_Init_Structure.Pull = GPIO_NOPULL; GPIO_Init_Structure.Speed = GPIO_SPEED_FAST; - GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC; + GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOI, &GPIO_Init_Structure); - // GPIOJ + // GPIOJ GPIO_Init_Structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \ GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | \ GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | \ - GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; + GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; GPIO_Init_Structure.Mode = GPIO_MODE_AF_PP; GPIO_Init_Structure.Pull = GPIO_NOPULL; GPIO_Init_Structure.Speed = GPIO_SPEED_FAST; - GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC; - HAL_GPIO_Init(GPIOJ, &GPIO_Init_Structure); + GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC; + HAL_GPIO_Init(GPIOJ, &GPIO_Init_Structure); - // GPIOK configuration + // GPIOK configuration GPIO_Init_Structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \ - GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; + GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; GPIO_Init_Structure.Mode = GPIO_MODE_AF_PP; GPIO_Init_Structure.Pull = GPIO_NOPULL; GPIO_Init_Structure.Speed = GPIO_SPEED_FAST; - GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC; + GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOK, &GPIO_Init_Structure); } 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; + (void) g; - switch(g->controllerdisplay) { - case 0: + // Set LCD pixel clock rate + configureLcdClock(); - // Set LCD pixel clock rate - configureLcdClock(); - - // Set pin directions - configureLcdPins(); + // Set pin directions + configureLcdPins(); - // Initialise the SDRAM - BSP_SDRAM_Init(); - - break; - } + // Initialise the SDRAM + BSP_SDRAM_Init(); } static GFXINLINE void post_init_board(GDisplay* g) diff --git a/boards/base/STM32F469i-Discovery/board_STM32LTDC.h b/boards/base/STM32F469i-Discovery/board_STM32LTDC.h index e58f566a..cd87d89e 100644 --- a/boards/base/STM32F469i-Discovery/board_STM32LTDC.h +++ b/boards/base/STM32F469i-Discovery/board_STM32LTDC.h @@ -27,6 +27,8 @@ static DSI_VidCfgTypeDef hdsivideo_handle; DSI_HandleTypeDef hdsi_eval; +#define ALLOW_2ND_LAYER FALSE // Do we really have the RAM bandwidth for this? + // Panel parameters // This panel is a KoD KM-040TMP-02-0621 DSI LCD Display. @@ -45,8 +47,8 @@ static const ltdcConfig driverCfg = { LTDC_PIXELFORMAT, // Pixel format 0, 0, // Start pixel position (x, y) 800, 480, // 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 @@ -54,18 +56,34 @@ 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+(800 * 480 * LTDC_PIXELBYTES)), // Frame buffer address + 800, 480, // Width, Height (pixels) + 800 * LTDC_PIXELBYTES, // Line pitch (bytes) + LTDC_PIXELFORMAT, // Pixel format + 0, 0, // Start pixel position (x, y) + 800, 480, // 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 }; /* Display timing */ #define KoD_FREQUENCY_DIVIDER 7 static GFXINLINE void init_board(GDisplay *g) { + (void) g; - // As we are not using multiple displays we set g->board to NULL as we don't use it - g->board = 0; - - DSI_PLLInitTypeDef dsiPllInit; + DSI_PLLInitTypeDef dsiPllInit; DSI_PHY_TimerTypeDef PhyTimings; // static RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; uint32_t LcdClock = 30000;//27429; /*!< LcdClk = 27429 kHz */ @@ -89,8 +107,8 @@ static GFXINLINE void init_board(GDisplay *g) { uint32_t HBP; /*!< Horizontal Back Porch time in units of lcdClk */ uint32_t HFP; /*!< Horizontal Front Porch time in units of lcdClk */ uint32_t HACT; /*!< Horizontal Active time in units of lcdClk = imageSize X in pixels to display */ - - + + /* Toggle Hardware Reset of the DSI LCD using * its XRES signal (active low) */ BSP_LCD_Reset(); @@ -102,19 +120,19 @@ static GFXINLINE void init_board(GDisplay *g) { * - NVIC IRQ related to IP blocks enabled */ BSP_LCD_MspInit(); - - /*************************DSI Initialization***********************************/ - + + /*************************DSI Initialization***********************************/ + /* Base address of DSI Host/Wrapper registers to be set before calling De-Init */ hdsi_eval.Instance = DSI; - + HAL_DSI_DeInit(&(hdsi_eval)); - + #if !defined(USE_STM32469I_DISCO_REVA) dsiPllInit.PLLNDIV = 125; dsiPllInit.PLLIDF = DSI_PLL_IN_DIV2; dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1; - #else + #else dsiPllInit.PLLNDIV = 100; dsiPllInit.PLLIDF = DSI_PLL_IN_DIV5; dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1; @@ -123,10 +141,10 @@ static GFXINLINE void init_board(GDisplay *g) { /* Set number of Lanes */ hdsi_eval.Init.NumberOfLanes = DSI_TWO_DATA_LANES; - + /* TXEscapeCkdiv = f(LaneByteClk)/15.62 = 4 */ - hdsi_eval.Init.TXEscapeCkdiv = laneByteClk_kHz/15620; - + hdsi_eval.Init.TXEscapeCkdiv = laneByteClk_kHz/15620; + HAL_DSI_Init(&(hdsi_eval), &(dsiPllInit)); /* Timing parameters for all Video modes @@ -139,7 +157,7 @@ static GFXINLINE void init_board(GDisplay *g) { HACT = lcd_x_size; VACT = lcd_y_size; - + /* The following values are same for portrait and landscape orientations */ VSA = 12;//OTM8009A_480X800_VSYNC; /* 12 */ VBP = 12;//OTM8009A_480X800_VBP; /* 12 */ @@ -152,11 +170,11 @@ static GFXINLINE void init_board(GDisplay *g) { hdsivideo_handle.ColorCoding = LCD_DSI_PIXEL_DATA_FMT_RBG888; hdsivideo_handle.VSPolarity = DSI_VSYNC_ACTIVE_HIGH; hdsivideo_handle.HSPolarity = DSI_HSYNC_ACTIVE_HIGH; - hdsivideo_handle.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH; + hdsivideo_handle.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH; hdsivideo_handle.Mode = DSI_VID_MODE_BURST; /* Mode Video burst ie : one LgP per line */ hdsivideo_handle.NullPacketSize = 0xFFF; hdsivideo_handle.NumberOfChunks = 0; - hdsivideo_handle.PacketSize = HACT; /* Value depending on display orientation choice portrait/landscape */ + hdsivideo_handle.PacketSize = HACT; /* Value depending on display orientation choice portrait/landscape */ hdsivideo_handle.HorizontalSyncActive = (HSA * laneByteClk_kHz) / LcdClock; hdsivideo_handle.HorizontalBackPorch = (HBP * laneByteClk_kHz) / LcdClock; hdsivideo_handle.HorizontalLine = ((HACT + HSA + HBP + HFP) * laneByteClk_kHz) / LcdClock; /* Value depending on display orientation choice portrait/landscape */ @@ -164,10 +182,10 @@ static GFXINLINE void init_board(GDisplay *g) { hdsivideo_handle.VerticalBackPorch = VBP; hdsivideo_handle.VerticalFrontPorch = VFP; hdsivideo_handle.VerticalActive = VACT; /* Value depending on display orientation choice portrait/landscape */ - + /* Enable or disable sending LP command while streaming is active in video mode */ hdsivideo_handle.LPCommandEnable = DSI_LP_COMMAND_ENABLE; /* Enable sending commands in mode LP (Low Power) */ - + /* Largest packet size possible to transmit in LP mode in VSA, VBP, VFP regions */ /* Only useful when sending LP packets is allowed while streaming is active in video mode */ hdsivideo_handle.LPLargestPacketSize = 16; @@ -184,7 +202,7 @@ static GFXINLINE void init_board(GDisplay *g) { hdsivideo_handle.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE; /* Allow sending LP commands during VFP period */ hdsivideo_handle.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE; /* Allow sending LP commands during VBP period */ hdsivideo_handle.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; /* Allow sending LP commands during VSync = VSA period */ - + /* Configure DSI Video mode timings with settings set above */ HAL_DSI_ConfigVideoMode(&(hdsi_eval), &(hdsivideo_handle)); @@ -197,7 +215,7 @@ static GFXINLINE void init_board(GDisplay *g) { PhyTimings.StopWaitTime = 10; HAL_DSI_ConfigPhyTimer(&hdsi_eval, &PhyTimings); - /*************************End DSI Initialization*******************************/ + /*************************End DSI Initialization*******************************/ /************************LTDC Initialization***********************************/ @@ -241,32 +259,28 @@ static GFXINLINE void init_board(GDisplay *g) { /* Initialize the SDRAM */ BSP_SDRAM_Init(); #endif /* DATA_IN_ExtSDRAM */ + } static GFXINLINE void post_init_board(GDisplay* g) { (void)g; - + + if (g->controllerdisplay) + return; + /* Initialize the font */ BSP_LCD_SetFont(&LCD_DEFAULT_FONT); - + /************************End LTDC Initialization*******************************/ - - - /***********************OTM8009A Initialization********************************/ - + + + /***********************OTM8009A Initialization********************************/ + /* Initialize the OTM8009A LCD Display IC Driver (KoD LCD IC Driver) * depending on configuration set in 'hdsivideo_handle'. */ OTM8009A_Init(OTM8009A_FORMAT_RGB888, OTM8009A_ORIENTATION_LANDSCAPE); - - /***********************End OTM8009A Initialization****************************/ - - // ------------------------------------------------------------------------ - - //BSP_LCD_LayerDefaultInit(LTDC_ACTIVE_LAYER_BACKGROUND, LCD_FB_START_ADDRESS); - //BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER_BACKGROUND); - //BSP_LCD_SetLayerVisible(LTDC_ACTIVE_LAYER_FOREGROUND, DISABLE); } static GFXINLINE void set_backlight(GDisplay* g, uint8_t percent) diff --git a/boards/base/STM32F746-Discovery/board_STM32LTDC.h b/boards/base/STM32F746-Discovery/board_STM32LTDC.h index 91f36b7e..8ad0dfa4 100644 --- a/boards/base/STM32F746-Discovery/board_STM32LTDC.h +++ b/boards/base/STM32F746-Discovery/board_STM32LTDC.h @@ -36,6 +36,8 @@ #define AFRH AFR[1] #endif +#define ALLOW_2ND_LAYER TRUE + static const ltdcConfig driverCfg = { 480, 272, // Width, Height (pixels) 41, 10, // Horizontal, Vertical sync (pixels) @@ -51,8 +53,8 @@ static const ltdcConfig driverCfg = { 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 @@ -60,7 +62,25 @@ 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 void configureLcdPins(void) { @@ -97,10 +117,10 @@ static void configureLcdPins(void) { palSetPadMode(GPIOI, GPIOI_LCD_DISP, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); // PI12: LCD_DISP_PIN palSetPadMode(GPIOK, GPIOK_LCD_BL_CTRL, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); // PK3 : LCD_BL_CTRL #else - + //------------------------------------------- // Initialise port PE - + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN; GPIOE->MODER |= ( GPIO_MODER_MODER4_1 // PE4: LCD_B0 - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(14) @@ -123,7 +143,7 @@ static void configureLcdPins(void) { //------------------------------------------- // Initialise port PG - + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN; GPIOG->MODER |= ( GPIO_MODER_MODER12_1 // PG12: LCD_B4 - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(9) @@ -143,10 +163,10 @@ static void configureLcdPins(void) { GPIOG->AFRH |= ( ( 9U << 4*(12-8)) ); - + //------------------------------------------- // Initialise port PI - + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOIEN; GPIOI->MODER |= ( GPIO_MODER_MODER9_1 // PI9: LCD_VSYNC - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(14) @@ -374,77 +394,66 @@ static void configureLcdPins(void) { } static GFXINLINE void init_board(GDisplay *g) { + (void) g; - // As we are not using multiple displays we set g->board to NULL as we don't use it - g->board = 0; + // Set pin directions + configureLcdPins(); - switch(g->controllerdisplay) { - case 0: + // Enable the display and turn on the backlight + #if GFX_USE_OS_CHIBIOS && !GFX_LTDC_USE_DIRECTIO + palSetPad(GPIOI, GPIOI_LCD_DISP); + palSetPad(GPIOK, GPIOK_LCD_BL_CTRL); + #else + GPIOI->ODR |= (1 << 12); // PowerOn + GPIOK->ODR |= (1 << 3); // Backlight on + #endif - // Set pin directions - configureLcdPins(); + #if GFX_LTDC_TIMING_SET != 0 + #define STM32_SAISRC_NOCLOCK (0 << 23) /**< No clock. */ + #define STM32_SAISRC_PLL (1 << 23) /**< SAI_CKIN is PLL. */ + #define STM32_SAIR_DIV2 (0 << 16) /**< R divided by 2. */ + #define STM32_SAIR_DIV4 (1 << 16) /**< R divided by 4. */ + #define STM32_SAIR_DIV8 (2 << 16) /**< R divided by 8. */ + #define STM32_SAIR_DIV16 (3 << 16) /**< R divided by 16. */ - // Enable the display and turn on the backlight - #if GFX_USE_OS_CHIBIOS && !GFX_LTDC_USE_DIRECTIO - palSetPad(GPIOI, GPIOI_LCD_DISP); - palSetPad(GPIOK, GPIOK_LCD_BL_CTRL); - #else - GPIOI->ODR |= (1 << 12); // PowerOn - GPIOK->ODR |= (1 << 3); // Backlight on - #endif + // Some operating systems get these wrong eg ChibiOS - define our own values + #undef STM32_PLLSAIN_VALUE + #undef STM32_PLLSAIQ_VALUE + #undef STM32_PLLSAIP_VALUE + #undef STM32_PLLSAIR_VALUE - #if GFX_LTDC_TIMING_SET != 0 - #define STM32_SAISRC_NOCLOCK (0 << 23) /**< No clock. */ - #define STM32_SAISRC_PLL (1 << 23) /**< SAI_CKIN is PLL. */ - #define STM32_SAIR_DIV2 (0 << 16) /**< R divided by 2. */ - #define STM32_SAIR_DIV4 (1 << 16) /**< R divided by 4. */ - #define STM32_SAIR_DIV8 (2 << 16) /**< R divided by 8. */ - #define STM32_SAIR_DIV16 (3 << 16) /**< R divided by 16. */ + /* Display timing */ + // RK043FN48H LCD clock configuration + // PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz + // PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz + // PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz + // LTDC clock frequency = PLLLCDCLK / STM32_PLLSAIR_POST = 38.4/4 = 9.6Mhz + #if GFX_LTDC_TIMING_SET == 1 + #define RK043FN48H_FREQUENCY_DIVIDER 5 + #define STM32_PLLSAIN_VALUE 192 + #define STM32_PLLSAIQ_VALUE 4 + #define STM32_PLLSAIP_VALUE 4 + #define STM32_PLLSAIR_VALUE RK043FN48H_FREQUENCY_DIVIDER + #define STM32_PLLSAIR_POST STM32_SAIR_DIV4 + #elif GFX_LTDC_TIMING_SET == 2 + #define RK043FN48H_FREQUENCY_DIVIDER 4 + #define STM32_PLLSAIN_VALUE 192 + #define STM32_PLLSAIQ_VALUE 4 + #define STM32_PLLSAIP_VALUE 4 + #define STM32_PLLSAIR_VALUE RK043FN48H_FREQUENCY_DIVIDER + #define STM32_PLLSAIR_POST STM32_SAIR_DIV4 + #else + #error "LTDC: - Unknown timing set for the STM32F746-Discovery board" + #endif - // Some operating systems get these wrong eg ChibiOS - define our own values - #undef STM32_PLLSAIN_VALUE - #undef STM32_PLLSAIQ_VALUE - #undef STM32_PLLSAIP_VALUE - #undef STM32_PLLSAIR_VALUE + RCC->CR &= ~RCC_CR_PLLSAION; + RCC->PLLSAICFGR = ((STM32_PLLSAIP_VALUE/2-1)<<16) | (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24); + RCC->DCKCFGR1 = (RCC->DCKCFGR1 & ~RCC_DCKCFGR1_PLLSAIDIVR) | STM32_PLLSAIR_POST; + RCC->CR |= RCC_CR_PLLSAION; + #endif - /* Display timing */ - // RK043FN48H LCD clock configuration - // PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz - // PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz - // PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz - // LTDC clock frequency = PLLLCDCLK / STM32_PLLSAIR_POST = 38.4/4 = 9.6Mhz - #if GFX_LTDC_TIMING_SET == 1 - #define RK043FN48H_FREQUENCY_DIVIDER 5 - #define STM32_PLLSAIN_VALUE 192 - #define STM32_PLLSAIQ_VALUE 4 - #define STM32_PLLSAIP_VALUE 4 - #define STM32_PLLSAIR_VALUE RK043FN48H_FREQUENCY_DIVIDER - #define STM32_PLLSAIR_POST STM32_SAIR_DIV4 - #elif GFX_LTDC_TIMING_SET == 2 - #define RK043FN48H_FREQUENCY_DIVIDER 4 - #define STM32_PLLSAIN_VALUE 192 - #define STM32_PLLSAIQ_VALUE 4 - #define STM32_PLLSAIP_VALUE 4 - #define STM32_PLLSAIR_VALUE RK043FN48H_FREQUENCY_DIVIDER - #define STM32_PLLSAIR_POST STM32_SAIR_DIV4 - #else - #error "LTDC: - Unknown timing set for the STM32F746-Discovery board" - #endif - - RCC->CR &= ~RCC_CR_PLLSAION; - RCC->PLLSAICFGR = ((STM32_PLLSAIP_VALUE/2-1)<<16) | (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24); - RCC->DCKCFGR1 = (RCC->DCKCFGR1 & ~RCC_DCKCFGR1_PLLSAIDIVR) | STM32_PLLSAIR_POST; - RCC->CR |= RCC_CR_PLLSAION; - #endif - - // Initialise the SDRAM - BSP_SDRAM_Init(); - - // Clear the SDRAM - //memset((void *)SDRAM_BANK_ADDR, 0, 0x400000); - - break; - } + // Initialise the SDRAM + BSP_SDRAM_Init(); } static GFXINLINE void post_init_board(GDisplay* g) { diff --git a/changelog.txt b/changelog.txt index bef1a884..79294ef0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -51,6 +51,15 @@ FEATURE: Added gwinTextEditSendKey() and gwinTextEditSendSpecialKey() FEATURE: Implemented the JPG image decoder FEATURE: Added SSD1322 driver FEATURE: Added support for Zephyr operating system +FEATURE: STM32LTDC driver now supports using both layers as seperate displays. The 2nd display is the foreground layer +CHANGE: STM32LTDC driver now uses RGB888 pixel format by default +FEATURE: Added GDISP_LTDC_USE_RGB565 config variable to force STM32LTDC driver to use RGB565 pixel format +FEATURE: The STM32LTDC 2nd display (the foreground layer) supports alpha. +FEATURE: The STM32 board files for known boards have been updated to contain support for the 2nd layer. +FEATURE: Added AHTML2COLOR() and ARGB2COLOR() to support alpha. This is currently only supported for the RGB888 pixel format. +FEATURE: Added the new color GFXTRANSPARENT - only available for RGB888 pixel format on alpha capable displays. +NOTE: Alpha support in RGB888 requies an alpha capable display (STM32LTDC 2nd display only currently) +NOTE: Alpha support in RGB888 is NOT the standard ARGB8888 format. Only use AHTML2COLOR() and ARGB2COLOR() to create alpha colors. *** Release 2.7 *** diff --git a/demos/modules/gdisp/multiple_displays/gfxconf.h b/demos/modules/gdisp/multiple_displays/gfxconf.h index 42e0b5e8..af71500e 100644 --- a/demos/modules/gdisp/multiple_displays/gfxconf.h +++ b/demos/modules/gdisp/multiple_displays/gfxconf.h @@ -84,7 +84,7 @@ //#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 #elif !defined(GDISP_TOTAL_DISPLAYS) && (!defined(GDISP_PIXELFORMAT) || !defined(GDISP_DRIVER_LIST)) - #error "gfxconf.h: You have not defined multiple displays properly. Try defining GDISP_TOTAL_DISPLAY or, GDISP_PIXELFORMAT and GDISP_DRIVER_LIST in your makefile" + #error "gfxconf.h: You have not defined multiple displays properly. Try defining GDISP_TOTAL_DISPLAYS or, GDISP_PIXELFORMAT and GDISP_DRIVER_LIST in your makefile" #endif /* 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 - // Finish Init the board - post_init_board(g); + if (!(driverCfg.bglayer.layerflags & LTDC_LEF_ENABLE)) + return FALSE; - // Turn on the back-light - set_backlight(g, GDISP_INITIAL_BACKLIGHT); + 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; + + // Load the foreground layer + _ltdc_layer_init(LTDC_Layer2, &driverCfg.fglayer); + _ltdc_reload(); + + 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 */ diff --git a/src/gdisp/gdisp_colors.h b/src/gdisp/gdisp_colors.h index 8c72f9ac..5bfcfca2 100644 --- a/src/gdisp/gdisp_colors.h +++ b/src/gdisp/gdisp_colors.h @@ -328,6 +328,13 @@ typedef uint16_t colorformat; #endif #define HTML2COLOR(h) ((COLOR_TYPE)(HTML2COLOR_R(h) | HTML2COLOR_G(h) | HTML2COLOR_B(h))) + // Special hack to allow alpha on RGB888 + #if GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888 + #define GFXTRANSPARENT (0xFF000000) + #define AHTML2COLOR(h) ((h) ^ 0xFF000000) + #define ARGB2COLOR(a,r,g,b) ((((COLOR_TYPE)(((a) ^ 0xFF) & 0xFF)) << 24) | RGB2COLOR_R(r) | RGB2COLOR_G(g) | RGB2COLOR_B(b)) + #endif + //------------------------- // Gray-scale color system //-------------------------