STM32LTDC 2nd layer support with alpha

release/v2.9
inmarket 2017-10-01 18:00:49 +10:00
parent 70222f8c8d
commit 82047b1ac6
10 changed files with 375 additions and 244 deletions

View File

@ -23,6 +23,8 @@ static const SPIConfig spi_cfg = {
((1 << 3) & SPI_CR1_BR) | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR ((1 << 3) & SPI_CR1_BR) | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR
}; };
#define ALLOW_2ND_LAYER TRUE
static const ltdcConfig driverCfg = { static const ltdcConfig driverCfg = {
240, 320, 240, 320,
10, 2, 10, 2,
@ -37,15 +39,33 @@ static const ltdcConfig driverCfg = {
LTDC_PIXELFORMAT, // fmt LTDC_PIXELFORMAT, // fmt
0, 0, // x, y 0, 0, // x, y
240, 320, // cx, cy 240, 320, // cx, cy
LTDC_COLOR_FUCHSIA, // defcolor 0x00000000, // defcolor
0x980088, // keycolor 0x000000, // keycolor
LTDC_BLEND_FIX1_FIX2, // blending LTDC_BLEND_FIX1_FIX2, // blending
0, // palette 0, // palette
0, // palettelen 0, // palettelen
0xFF, // alpha 0xFF, // alpha
LTDC_LEF_ENABLE // flags 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 LTDC_UNUSED_LAYER_CONFIG
#endif
}; };
#include "ili9341.h" #include "ili9341.h"
@ -146,45 +166,39 @@ static void Init9341(GDisplay *g) {
} }
static void init_board(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. palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7)); // UART_TX
g->board = 0; 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) { #define STM32_SAISRC_NOCLOCK (0 << 23) /**< No clock. */
case 0: // Set up for Display 0 #define STM32_SAISRC_PLL (1 << 23) /**< SAI_CKIN is PLL. */
palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7)); // UART_TX #define STM32_SAIR_DIV2 (0 << 16) /**< R divided by 2. */
palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7)); // UART_RX #define STM32_SAIR_DIV4 (1 << 16) /**< R divided by 4. */
palSetPadMode(GPIOF, GPIOF_LCD_DCX, PAL_MODE_ALTERNATE(5)); #define STM32_SAIR_DIV8 (2 << 16) /**< R divided by 8. */
palSetPadMode(GPIOF, GPIOF_LCD_DE, PAL_MODE_ALTERNATE(14)); #define STM32_SAIR_DIV16 (3 << 16) /**< R divided by 16. */
#define STM32_SAISRC_NOCLOCK (0 << 23) /**< No clock. */ #define STM32_PLLSAIN_VALUE 192
#define STM32_SAISRC_PLL (1 << 23) /**< SAI_CKIN is PLL. */ #define STM32_PLLSAIQ_VALUE 7
#define STM32_SAIR_DIV2 (0 << 16) /**< R divided by 2. */ #define STM32_PLLSAIR_VALUE 4
#define STM32_SAIR_DIV4 (1 << 16) /**< R divided by 4. */ #define STM32_PLLSAIR_POST STM32_SAIR_DIV4
#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 /* PLLSAI activation.*/
#define STM32_PLLSAIQ_VALUE 7 RCC->PLLSAICFGR = (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24);
#define STM32_PLLSAIR_VALUE 4 RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | STM32_PLLSAIR_POST;
#define STM32_PLLSAIR_POST STM32_SAIR_DIV4 RCC->CR |= RCC_CR_PLLSAION;
/* PLLSAI activation.*/ // Initialise the SDRAM
RCC->PLLSAICFGR = (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24); SDRAM_Init();
RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | STM32_PLLSAIR_POST;
RCC->CR |= RCC_CR_PLLSAION;
// Initialise the SDRAM // Clear the SDRAM
SDRAM_Init(); memset((void *)SDRAM_BANK_ADDR, 0, 0x400000);
// Clear the SDRAM spiStart(SPI_PORT, &spi_cfg);
memset((void *)SDRAM_BANK_ADDR, 0, 0x400000);
spiStart(SPI_PORT, &spi_cfg); Init9341(g);
Init9341(g);
break;
}
} }
static GFXINLINE void post_init_board(GDisplay *g) { static GFXINLINE void post_init_board(GDisplay *g) {

View File

@ -17,6 +17,8 @@
#include "stm32f4xx_hal.h" #include "stm32f4xx_hal.h"
#include "stm324x9i_eval_sdram.h" #include "stm324x9i_eval_sdram.h"
#define ALLOW_2ND_LAYER TRUE
// Panel parameters // Panel parameters
// This panel is a AMPIRE640480 panel. // This panel is a AMPIRE640480 panel.
@ -35,8 +37,8 @@ static const ltdcConfig driverCfg = {
LTDC_PIXELFORMAT, // Pixel format LTDC_PIXELFORMAT, // Pixel format
0, 0, // Start pixel position (x, y) 0, 0, // Start pixel position (x, y)
640, 480, // Size of virtual layer (cx, cy) 640, 480, // Size of virtual layer (cx, cy)
LTDC_COLOR_FUCHSIA, // Default color (ARGB8888) 0x00000000, // Default color (ARGB8888)
0x980088, // Color key (RGB888) 0x000000, // Color key (RGB888)
LTDC_BLEND_FIX1_FIX2, // Blending factors LTDC_BLEND_FIX1_FIX2, // Blending factors
0, // Palette (RGB888, can be NULL) 0, // Palette (RGB888, can be NULL)
0, // Palette length 0, // Palette length
@ -44,7 +46,25 @@ static const ltdcConfig driverCfg = {
LTDC_LEF_ENABLE // Layer configuration flags 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 // LCD Clock values
@ -56,10 +76,10 @@ static void configureLcdClock(void)
{ {
#if 1 #if 1
RCC_PeriphCLKInitTypeDef periph_clk_init_struct; RCC_PeriphCLKInitTypeDef periph_clk_init_struct;
periph_clk_init_struct.PLLSAI.PLLSAIN = LCD_PLLSAIN_VALUE; periph_clk_init_struct.PLLSAI.PLLSAIN = LCD_PLLSAIN_VALUE;
periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
periph_clk_init_struct.PLLSAI.PLLSAIR = LCD_PLLSAIR_VALUE; periph_clk_init_struct.PLLSAI.PLLSAIR = LCD_PLLSAIR_VALUE;
periph_clk_init_struct.PLLSAIDivR = LCD_PLLSAIDIVR_VALUE; periph_clk_init_struct.PLLSAIDivR = LCD_PLLSAIDIVR_VALUE;
HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct); HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct);
#else #else
@ -77,59 +97,52 @@ static void configureLcdPins(void)
GPIO_InitTypeDef GPIO_Init_Structure; GPIO_InitTypeDef GPIO_Init_Structure;
// Enable peripheral clocks // Enable peripheral clocks
__GPIOI_CLK_ENABLE(); __GPIOI_CLK_ENABLE();
__GPIOJ_CLK_ENABLE(); __GPIOJ_CLK_ENABLE();
__GPIOK_CLK_ENABLE(); __GPIOK_CLK_ENABLE();
/*** LTDC Pins configuration ***/ /*** LTDC Pins configuration ***/
// GPIOI // 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.Mode = GPIO_MODE_AF_PP;
GPIO_Init_Structure.Pull = GPIO_NOPULL; GPIO_Init_Structure.Pull = GPIO_NOPULL;
GPIO_Init_Structure.Speed = GPIO_SPEED_FAST; 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); 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_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_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | \ 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.Mode = GPIO_MODE_AF_PP;
GPIO_Init_Structure.Pull = GPIO_NOPULL; GPIO_Init_Structure.Pull = GPIO_NOPULL;
GPIO_Init_Structure.Speed = GPIO_SPEED_FAST; GPIO_Init_Structure.Speed = GPIO_SPEED_FAST;
GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC; GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(GPIOJ, &GPIO_Init_Structure); 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_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.Mode = GPIO_MODE_AF_PP;
GPIO_Init_Structure.Pull = GPIO_NOPULL; GPIO_Init_Structure.Pull = GPIO_NOPULL;
GPIO_Init_Structure.Speed = GPIO_SPEED_FAST; 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); HAL_GPIO_Init(GPIOK, &GPIO_Init_Structure);
} }
static GFXINLINE void init_board(GDisplay* g) 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 (void) g;
g->board = 0;
switch(g->controllerdisplay) { // Set LCD pixel clock rate
case 0: configureLcdClock();
// Set LCD pixel clock rate // Set pin directions
configureLcdClock(); configureLcdPins();
// Set pin directions
configureLcdPins();
// Initialise the SDRAM // Initialise the SDRAM
BSP_SDRAM_Init(); BSP_SDRAM_Init();
break;
}
} }
static GFXINLINE void post_init_board(GDisplay* g) static GFXINLINE void post_init_board(GDisplay* g)

View File

@ -27,6 +27,8 @@
static DSI_VidCfgTypeDef hdsivideo_handle; static DSI_VidCfgTypeDef hdsivideo_handle;
DSI_HandleTypeDef hdsi_eval; DSI_HandleTypeDef hdsi_eval;
#define ALLOW_2ND_LAYER FALSE // Do we really have the RAM bandwidth for this?
// Panel parameters // Panel parameters
// This panel is a KoD KM-040TMP-02-0621 DSI LCD Display. // This panel is a KoD KM-040TMP-02-0621 DSI LCD Display.
@ -45,8 +47,8 @@ static const ltdcConfig driverCfg = {
LTDC_PIXELFORMAT, // Pixel format LTDC_PIXELFORMAT, // Pixel format
0, 0, // Start pixel position (x, y) 0, 0, // Start pixel position (x, y)
800, 480, // Size of virtual layer (cx, cy) 800, 480, // Size of virtual layer (cx, cy)
LTDC_COLOR_FUCHSIA, // Default color (ARGB8888) 0x00000000, // Default color (ARGB8888)
0x980088, // Color key (RGB888) 0x000000, // Color key (RGB888)
LTDC_BLEND_FIX1_FIX2, // Blending factors LTDC_BLEND_FIX1_FIX2, // Blending factors
0, // Palette (RGB888, can be NULL) 0, // Palette (RGB888, can be NULL)
0, // Palette length 0, // Palette length
@ -54,18 +56,34 @@ static const ltdcConfig driverCfg = {
LTDC_LEF_ENABLE // Layer configuration flags 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 */ /* Display timing */
#define KoD_FREQUENCY_DIVIDER 7 #define KoD_FREQUENCY_DIVIDER 7
static GFXINLINE void init_board(GDisplay *g) { 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 DSI_PLLInitTypeDef dsiPllInit;
g->board = 0;
DSI_PLLInitTypeDef dsiPllInit;
DSI_PHY_TimerTypeDef PhyTimings; DSI_PHY_TimerTypeDef PhyTimings;
// static RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; // static RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
uint32_t LcdClock = 30000;//27429; /*!< LcdClk = 27429 kHz */ 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 HBP; /*!< Horizontal Back Porch time in units of lcdClk */
uint32_t HFP; /*!< Horizontal Front 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 */ uint32_t HACT; /*!< Horizontal Active time in units of lcdClk = imageSize X in pixels to display */
/* Toggle Hardware Reset of the DSI LCD using /* Toggle Hardware Reset of the DSI LCD using
* its XRES signal (active low) */ * its XRES signal (active low) */
BSP_LCD_Reset(); BSP_LCD_Reset();
@ -102,19 +120,19 @@ static GFXINLINE void init_board(GDisplay *g) {
* - NVIC IRQ related to IP blocks enabled * - NVIC IRQ related to IP blocks enabled
*/ */
BSP_LCD_MspInit(); BSP_LCD_MspInit();
/*************************DSI Initialization***********************************/ /*************************DSI Initialization***********************************/
/* Base address of DSI Host/Wrapper registers to be set before calling De-Init */ /* Base address of DSI Host/Wrapper registers to be set before calling De-Init */
hdsi_eval.Instance = DSI; hdsi_eval.Instance = DSI;
HAL_DSI_DeInit(&(hdsi_eval)); HAL_DSI_DeInit(&(hdsi_eval));
#if !defined(USE_STM32469I_DISCO_REVA) #if !defined(USE_STM32469I_DISCO_REVA)
dsiPllInit.PLLNDIV = 125; dsiPllInit.PLLNDIV = 125;
dsiPllInit.PLLIDF = DSI_PLL_IN_DIV2; dsiPllInit.PLLIDF = DSI_PLL_IN_DIV2;
dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1; dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1;
#else #else
dsiPllInit.PLLNDIV = 100; dsiPllInit.PLLNDIV = 100;
dsiPllInit.PLLIDF = DSI_PLL_IN_DIV5; dsiPllInit.PLLIDF = DSI_PLL_IN_DIV5;
dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1; dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1;
@ -123,10 +141,10 @@ static GFXINLINE void init_board(GDisplay *g) {
/* Set number of Lanes */ /* Set number of Lanes */
hdsi_eval.Init.NumberOfLanes = DSI_TWO_DATA_LANES; hdsi_eval.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
/* TXEscapeCkdiv = f(LaneByteClk)/15.62 = 4 */ /* 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)); HAL_DSI_Init(&(hdsi_eval), &(dsiPllInit));
/* Timing parameters for all Video modes /* Timing parameters for all Video modes
@ -139,7 +157,7 @@ static GFXINLINE void init_board(GDisplay *g) {
HACT = lcd_x_size; HACT = lcd_x_size;
VACT = lcd_y_size; VACT = lcd_y_size;
/* The following values are same for portrait and landscape orientations */ /* The following values are same for portrait and landscape orientations */
VSA = 12;//OTM8009A_480X800_VSYNC; /* 12 */ VSA = 12;//OTM8009A_480X800_VSYNC; /* 12 */
VBP = 12;//OTM8009A_480X800_VBP; /* 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.ColorCoding = LCD_DSI_PIXEL_DATA_FMT_RBG888;
hdsivideo_handle.VSPolarity = DSI_VSYNC_ACTIVE_HIGH; hdsivideo_handle.VSPolarity = DSI_VSYNC_ACTIVE_HIGH;
hdsivideo_handle.HSPolarity = DSI_HSYNC_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.Mode = DSI_VID_MODE_BURST; /* Mode Video burst ie : one LgP per line */
hdsivideo_handle.NullPacketSize = 0xFFF; hdsivideo_handle.NullPacketSize = 0xFFF;
hdsivideo_handle.NumberOfChunks = 0; 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.HorizontalSyncActive = (HSA * laneByteClk_kHz) / LcdClock;
hdsivideo_handle.HorizontalBackPorch = (HBP * 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 */ 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.VerticalBackPorch = VBP;
hdsivideo_handle.VerticalFrontPorch = VFP; hdsivideo_handle.VerticalFrontPorch = VFP;
hdsivideo_handle.VerticalActive = VACT; /* Value depending on display orientation choice portrait/landscape */ 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 */ /* 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) */ 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 */ /* 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 */ /* Only useful when sending LP packets is allowed while streaming is active in video mode */
hdsivideo_handle.LPLargestPacketSize = 16; 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.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.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 */ hdsivideo_handle.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; /* Allow sending LP commands during VSync = VSA period */
/* Configure DSI Video mode timings with settings set above */ /* Configure DSI Video mode timings with settings set above */
HAL_DSI_ConfigVideoMode(&(hdsi_eval), &(hdsivideo_handle)); HAL_DSI_ConfigVideoMode(&(hdsi_eval), &(hdsivideo_handle));
@ -197,7 +215,7 @@ static GFXINLINE void init_board(GDisplay *g) {
PhyTimings.StopWaitTime = 10; PhyTimings.StopWaitTime = 10;
HAL_DSI_ConfigPhyTimer(&hdsi_eval, &PhyTimings); HAL_DSI_ConfigPhyTimer(&hdsi_eval, &PhyTimings);
/*************************End DSI Initialization*******************************/ /*************************End DSI Initialization*******************************/
/************************LTDC Initialization***********************************/ /************************LTDC Initialization***********************************/
@ -241,32 +259,28 @@ static GFXINLINE void init_board(GDisplay *g) {
/* Initialize the SDRAM */ /* Initialize the SDRAM */
BSP_SDRAM_Init(); BSP_SDRAM_Init();
#endif /* DATA_IN_ExtSDRAM */ #endif /* DATA_IN_ExtSDRAM */
} }
static GFXINLINE void post_init_board(GDisplay* g) static GFXINLINE void post_init_board(GDisplay* g)
{ {
(void)g; (void)g;
if (g->controllerdisplay)
return;
/* Initialize the font */ /* Initialize the font */
BSP_LCD_SetFont(&LCD_DEFAULT_FONT); BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
/************************End LTDC Initialization*******************************/ /************************End LTDC Initialization*******************************/
/***********************OTM8009A Initialization********************************/ /***********************OTM8009A Initialization********************************/
/* Initialize the OTM8009A LCD Display IC Driver (KoD LCD IC Driver) /* Initialize the OTM8009A LCD Display IC Driver (KoD LCD IC Driver)
* depending on configuration set in 'hdsivideo_handle'. * depending on configuration set in 'hdsivideo_handle'.
*/ */
OTM8009A_Init(OTM8009A_FORMAT_RGB888, OTM8009A_ORIENTATION_LANDSCAPE); 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) static GFXINLINE void set_backlight(GDisplay* g, uint8_t percent)

View File

@ -36,6 +36,8 @@
#define AFRH AFR[1] #define AFRH AFR[1]
#endif #endif
#define ALLOW_2ND_LAYER TRUE
static const ltdcConfig driverCfg = { static const ltdcConfig driverCfg = {
480, 272, // Width, Height (pixels) 480, 272, // Width, Height (pixels)
41, 10, // Horizontal, Vertical sync (pixels) 41, 10, // Horizontal, Vertical sync (pixels)
@ -51,8 +53,8 @@ static const ltdcConfig driverCfg = {
LTDC_PIXELFORMAT, // Pixel format LTDC_PIXELFORMAT, // Pixel format
0, 0, // Start pixel position (x, y) 0, 0, // Start pixel position (x, y)
480, 272, // Size of virtual layer (cx, cy) 480, 272, // Size of virtual layer (cx, cy)
LTDC_COLOR_FUCHSIA, // Default color (ARGB8888) 0x00000000, // Default color (ARGB8888)
0x980088, // Color key (RGB888) 0x000000, // Color key (RGB888)
LTDC_BLEND_FIX1_FIX2, // Blending factors LTDC_BLEND_FIX1_FIX2, // Blending factors
0, // Palette (RGB888, can be NULL) 0, // Palette (RGB888, can be NULL)
0, // Palette length 0, // Palette length
@ -60,7 +62,25 @@ static const ltdcConfig driverCfg = {
LTDC_LEF_ENABLE // Layer configuration flags 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) { 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(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 palSetPadMode(GPIOK, GPIOK_LCD_BL_CTRL, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); // PK3 : LCD_BL_CTRL
#else #else
//------------------------------------------- //-------------------------------------------
// Initialise port PE // Initialise port PE
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;
GPIOE->MODER |= ( GPIOE->MODER |= (
GPIO_MODER_MODER4_1 // PE4: LCD_B0 - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(14) 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 // Initialise port PG
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
GPIOG->MODER |= ( GPIOG->MODER |= (
GPIO_MODER_MODER12_1 // PG12: LCD_B4 - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(9) 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 |= ( GPIOG->AFRH |= (
( 9U << 4*(12-8)) ( 9U << 4*(12-8))
); );
//------------------------------------------- //-------------------------------------------
// Initialise port PI // Initialise port PI
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOIEN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOIEN;
GPIOI->MODER |= ( GPIOI->MODER |= (
GPIO_MODER_MODER9_1 // PI9: LCD_VSYNC - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(14) 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) { 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 // Set pin directions
g->board = 0; configureLcdPins();
switch(g->controllerdisplay) { // Enable the display and turn on the backlight
case 0: #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 #if GFX_LTDC_TIMING_SET != 0
configureLcdPins(); #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 // Some operating systems get these wrong eg ChibiOS - define our own values
#if GFX_USE_OS_CHIBIOS && !GFX_LTDC_USE_DIRECTIO #undef STM32_PLLSAIN_VALUE
palSetPad(GPIOI, GPIOI_LCD_DISP); #undef STM32_PLLSAIQ_VALUE
palSetPad(GPIOK, GPIOK_LCD_BL_CTRL); #undef STM32_PLLSAIP_VALUE
#else #undef STM32_PLLSAIR_VALUE
GPIOI->ODR |= (1 << 12); // PowerOn
GPIOK->ODR |= (1 << 3); // Backlight on
#endif
#if GFX_LTDC_TIMING_SET != 0 /* Display timing */
#define STM32_SAISRC_NOCLOCK (0 << 23) /**< No clock. */ // RK043FN48H LCD clock configuration
#define STM32_SAISRC_PLL (1 << 23) /**< SAI_CKIN is PLL. */ // PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz
#define STM32_SAIR_DIV2 (0 << 16) /**< R divided by 2. */ // PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz
#define STM32_SAIR_DIV4 (1 << 16) /**< R divided by 4. */ // PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz
#define STM32_SAIR_DIV8 (2 << 16) /**< R divided by 8. */ // LTDC clock frequency = PLLLCDCLK / STM32_PLLSAIR_POST = 38.4/4 = 9.6Mhz
#define STM32_SAIR_DIV16 (3 << 16) /**< R divided by 16. */ #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 RCC->CR &= ~RCC_CR_PLLSAION;
#undef STM32_PLLSAIN_VALUE RCC->PLLSAICFGR = ((STM32_PLLSAIP_VALUE/2-1)<<16) | (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24);
#undef STM32_PLLSAIQ_VALUE RCC->DCKCFGR1 = (RCC->DCKCFGR1 & ~RCC_DCKCFGR1_PLLSAIDIVR) | STM32_PLLSAIR_POST;
#undef STM32_PLLSAIP_VALUE RCC->CR |= RCC_CR_PLLSAION;
#undef STM32_PLLSAIR_VALUE #endif
/* Display timing */ // Initialise the SDRAM
// RK043FN48H LCD clock configuration BSP_SDRAM_Init();
// 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;
}
} }
static GFXINLINE void post_init_board(GDisplay* g) { static GFXINLINE void post_init_board(GDisplay* g) {

View File

@ -51,6 +51,15 @@ FEATURE: Added gwinTextEditSendKey() and gwinTextEditSendSpecialKey()
FEATURE: Implemented the JPG image decoder FEATURE: Implemented the JPG image decoder
FEATURE: Added SSD1322 driver FEATURE: Added SSD1322 driver
FEATURE: Added support for Zephyr operating system 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 *** *** Release 2.7 ***

View File

@ -84,7 +84,7 @@
//#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 //#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
#elif !defined(GDISP_TOTAL_DISPLAYS) && (!defined(GDISP_PIXELFORMAT) || !defined(GDISP_DRIVER_LIST)) #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 #endif
/* /*

View File

@ -8,6 +8,8 @@
#ifndef _GDISP_LLD_BOARD_H #ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H #define _GDISP_LLD_BOARD_H
#define ALLOW_2ND_LAYER TRUE
static const ltdcConfig driverCfg = { static const ltdcConfig driverCfg = {
480, 272, // Width, Height (pixels) 480, 272, // Width, Height (pixels)
41, 10, // Horizontal, Vertical sync (pixels) 41, 10, // Horizontal, Vertical sync (pixels)
@ -17,14 +19,14 @@ static const ltdcConfig driverCfg = {
0x000000, // Clear color (RGB888) 0x000000, // Clear color (RGB888)
{ // Background layer config { // 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, 272, // Width, Height (pixels)
480 * LTDC_PIXELBYTES, // Line pitch (bytes) 480 * LTDC_PIXELBYTES, // Line pitch (bytes)
LTDC_PIXELFORMAT, // Pixel format LTDC_PIXELFORMAT, // Pixel format
0, 0, // Start pixel position (x, y) 0, 0, // Start pixel position (x, y)
480, 272, // Size of virtual layer (cx, cy) 480, 272, // Size of virtual layer (cx, cy)
LTDC_COLOR_FUCHSIA, // Default color (ARGB8888) 0x00000000, // Default color (ARGB8888)
0x980088, // Color key (RGB888) 0x000000, // Color key (RGB888)
LTDC_BLEND_FIX1_FIX2, // Blending factors LTDC_BLEND_FIX1_FIX2, // Blending factors
0, // Palette (RGB888, can be NULL) 0, // Palette (RGB888, can be NULL)
0, // Palette length 0, // Palette length
@ -32,28 +34,47 @@ static const ltdcConfig driverCfg = {
LTDC_LEF_ENABLE // Layer configuration flags 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) { static GFXINLINE void init_board(GDisplay* g) {
// This is function only called once with the display for the background layer.
// As we are not using multiple displays we set g->board to NULL as we don't use it. (void)g;
g->board = 0;
switch(g->controllerdisplay) {
case 0: // Set up for Display 0
// Your init here
break;
}
} }
static GFXINLINE void post_init_board(GDisplay* 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; (void)g;
} }
static GFXINLINE void set_backlight(GDisplay* g, uint8_t percent) 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)g;
(void)percent; (void)percent;
} }

View File

@ -99,13 +99,15 @@ typedef struct ltdcConfig {
/* Driver local routines. */ /* Driver local routines. */
/*===========================================================================*/ /*===========================================================================*/
#define PIXIL_POS(g, x, y) ((y) * driverCfg.bglayer.pitch + (x) * LTDC_PIXELBYTES) #define PIXIL_POS(g, x, y) ((y) * ((ltdcLayerConfig *)g->priv)->pitch + (x) * LTDC_PIXELBYTES)
#define PIXEL_ADDR(g, pos) ((LLDCOLOR_TYPE *)((uint8_t *)driverCfg.bglayer.frame+pos)) #define PIXEL_ADDR(g, pos) ((LLDCOLOR_TYPE *)((uint8_t *)((ltdcLayerConfig *)g->priv)->frame+pos))
/*===========================================================================*/ /*===========================================================================*/
/* Driver exported functions. */ /* Driver exported functions. */
/*===========================================================================*/ /*===========================================================================*/
static const ltdcLayerConfig layerOff = LTDC_UNUSED_LAYER_CONFIG;
static void _ltdc_reload(void) { static void _ltdc_reload(void) {
LTDC->SRCR |= LTDC_SRCR_IMR; LTDC->SRCR |= LTDC_SRCR_IMR;
while (LTDC->SRCR & (LTDC_SRCR_IMR | LTDC_SRCR_VBR)) 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); _ltdc_layer_init(LTDC_Layer1, &driverCfg.bglayer);
// Load the foreground layer // Load the foreground layer
_ltdc_layer_init(LTDC_Layer2, &driverCfg.fglayer); _ltdc_layer_init(LTDC_Layer2, &layerOff);
// Interrupt handling // Interrupt handling
// Possible flags - LTDC_IER_RRIE, LTDC_IER_LIE, LTDC_IER_FUIE, LTDC_IER_TERRIE etc // 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->priv = 0;
g->board = 0; g->board = 0;
// Init the board switch(g->controllerdisplay) {
init_board(g); case 0: // Display 0 is the background layer
// Init the board
init_board(g);
// Initialise the LTDC controller // Initialise the LTDC controller
_ltdc_init(); _ltdc_init();
// Initialise DMA2D // Initialise DMA2D
#if LTDC_USE_DMA2D #if LTDC_USE_DMA2D
dma2d_init(); dma2d_init();
#endif #endif
// Finish Init the board if (!(driverCfg.bglayer.layerflags & LTDC_LEF_ENABLE))
post_init_board(g); return FALSE;
// Turn on the back-light g->priv = (void *)&driverCfg.bglayer;
set_backlight(g, GDISP_INITIAL_BACKLIGHT);
// 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 // Initialise the GDISP structure
g->g.Width = driverCfg.bglayer.width; g->g.Width = ((ltdcLayerConfig *)g->priv)->width;
g->g.Height = driverCfg.bglayer.height; g->g.Height = ((ltdcLayerConfig *)g->priv)->height;
g->g.Orientation = GDISP_ROTATE_0; g->g.Orientation = GDISP_ROTATE_0;
g->g.Powermode = powerOn; g->g.Powermode = powerOn;
g->g.Backlight = GDISP_INITIAL_BACKLIGHT; g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
@ -282,7 +313,14 @@ LLDSPEC void gdisp_lld_draw_pixel(GDisplay* g) {
while(DMA2D->CR & DMA2D_CR_START); while(DMA2D->CR & DMA2D_CR_START);
#endif #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) { 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); while(DMA2D->CR & DMA2D_CR_START);
#endif #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); return gdispNative2Color(color);
} }
#if GDISP_NEED_CONTROL #if GDISP_NEED_CONTROL
LLDSPEC void gdisp_lld_control(GDisplay* g) { LLDSPEC void gdisp_lld_control(GDisplay* g) {
switch(g->p.x) { 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: case GDISP_CONTROL_ORIENTATION:
if (g->g.Orientation == (orientation_t)g->p.ptr) if (g->g.Orientation == (orientation_t)g->p.ptr)
return; return;
@ -369,12 +401,6 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
set_backlight(g, (unsigned)g->p.ptr); set_backlight(g, (unsigned)g->p.ptr);
g->g.Backlight = (unsigned)g->p.ptr; g->g.Backlight = (unsigned)g->p.ptr;
return; 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 #endif
@ -383,14 +409,14 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
static void dma2d_init(void) { static void dma2d_init(void) {
// Enable DMA2D clock // Enable DMA2D clock
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN; RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
// Output color format // Output color format
#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
DMA2D->OPFCCR = OPFCCR_RGB565; DMA2D->OPFCCR = OPFCCR_RGB565;
#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888 #elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
DMA2D->OPFCCR = OPFCCR_ARGB8888; DMA2D->OPFCCR = OPFCCR_ARGB8888;
#endif #endif
// Foreground color format // Foreground color format
#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
DMA2D->FGPFCCR = FGPFCCR_CM_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 // Uses p.x,p.y p.cx,p.cy p.color
LLDSPEC void gdisp_lld_fill_area(GDisplay* g) LLDSPEC void gdisp_lld_fill_area(GDisplay* g)
{ {
uint32_t pos; uint32_t pos;
uint32_t lineadd; uint32_t lineadd;
uint32_t shape; uint32_t shape;
// Wait until DMA2D is ready
while(DMA2D->CR & DMA2D_CR_START);
#if GDISP_NEED_CONTROL #if GDISP_NEED_CONTROL
switch(g->g.Orientation) { switch(g->g.Orientation) {
case GDISP_ROTATE_0: 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; lineadd = g->g.Width - g->p.cx;
shape = (g->p.cx << 16) | (g->p.cy); shape = (g->p.cx << 16) | (g->p.cy);
#endif #endif
// Wait until DMA2D is ready
while(DMA2D->CR & DMA2D_CR_START);
// Start the DMA2D // Start the DMA2D
DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, pos); DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, pos);
DMA2D->OOR = lineadd; DMA2D->OOR = lineadd;
DMA2D->NLR = shape; DMA2D->NLR = shape;
DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color)); #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START; // 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. /* 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. * access to the framebuffer is fast - probably faster than DMA2D.
* It just uses more CPU. * 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) // 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) { LLDSPEC void gdisp_lld_blit_area(GDisplay* g) {
// Wait until DMA2D is ready // Wait until DMA2D is ready
@ -473,7 +507,7 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
// Source setup // Source setup
DMA2D->FGMAR = LTDC_PIXELBYTES * (g->p.y1 * g->p.x2 + g->p.x1) + (uint32_t)g->p.ptr; 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; DMA2D->FGOR = g->p.x2 - g->p.cx;
// Output setup // Output setup
DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, PIXIL_POS(g, g->p.x, g->p.y)); DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, PIXIL_POS(g, g->p.x, g->p.y));
DMA2D->OOR = g->g.Width - g->p.cx; DMA2D->OOR = g->g.Width - g->p.cx;

View File

@ -21,8 +21,15 @@
// Both these pixel formats are supported - pick one. // Both these pixel formats are supported - pick one.
// RGB565 obviously is faster and uses less RAM but with lower color resolution than RGB888 // 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 // Accelerated bitfills are also possible but only for GDISP_ROTATE_0
// and if no color translation is required (for now) // and if no color translation is required (for now)
#if !GDISP_NEED_CONTROL && GDISP_PIXELFORMAT == GDISP_LLD_PIXELFORMAT // Oops - this is not working and adds little performance benefit
#define GDISP_HARDWARE_BITFILLS TRUE // so we will just disable it for the near future.
#endif // #if !GDISP_NEED_CONTROL && !defined(GDISP_PIXELFORMAT)
// #define GDISP_HARDWARE_BITFILLS TRUE
// #endif
#endif /* GDISP_USE_DMA2D */ #endif /* GDISP_USE_DMA2D */
#endif /* GFX_USE_GDISP */ #endif /* GFX_USE_GDISP */

View File

@ -328,6 +328,13 @@ typedef uint16_t colorformat;
#endif #endif
#define HTML2COLOR(h) ((COLOR_TYPE)(HTML2COLOR_R(h) | HTML2COLOR_G(h) | HTML2COLOR_B(h))) #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 // Gray-scale color system
//------------------------- //-------------------------