Browse Source

STM32LTDC 2nd layer support with alpha

inmarket 3 years ago
parent
commit
82047b1ac6

+ 47 - 33
boards/base/STM32F429i-Discovery/board_STM32LTDC.h

@@ -23,6 +23,8 @@ static const SPIConfig spi_cfg = {
23 23
 	((1 << 3) & SPI_CR1_BR) | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR
24 24
 };
25 25
 
26
+#define ALLOW_2ND_LAYER		TRUE
27
+
26 28
 static const ltdcConfig driverCfg = {
27 29
 	240, 320,
28 30
 	10, 2,
@@ -37,15 +39,33 @@ static const ltdcConfig driverCfg = {
37 39
 		LTDC_PIXELFORMAT,					// fmt
38 40
 		0, 0,								// x, y
39 41
 		240, 320,							// cx, cy
40
-		LTDC_COLOR_FUCHSIA,					// defcolor
41
-		0x980088,							// keycolor
42
+		0x00000000,							// defcolor
43
+		0x000000,							// keycolor
42 44
 		LTDC_BLEND_FIX1_FIX2,				// blending
43 45
 		0,									// palette
44 46
 		0,									// palettelen
45 47
 		0xFF,								// alpha
46 48
 		LTDC_LEF_ENABLE						// flags
47 49
 	},
50
+#if ALLOW_2ND_LAYER
51
+	{										// Foreground layer config (if turned on)
52
+		(LLDCOLOR_TYPE *)(SDRAM_DEVICE_ADDR+(240 * 320 * LTDC_PIXELBYTES)), // Frame buffer address
53
+		240, 320,							// width, height
54
+		240 * LTDC_PIXELBYTES,				// pitch
55
+		LTDC_PIXELFORMAT,					// fmt
56
+		0, 0,								// x, y
57
+		240, 320,							// cx, cy
58
+		0x00000000,							// Default color (ARGB8888)
59
+		0x000000,							// Color key (RGB888)
60
+		LTDC_BLEND_MOD1_MOD2,				// Blending factors
61
+		0,									// Palette (RGB888, can be NULL)
62
+		0,									// Palette length
63
+		0xFF,								// Constant alpha factor
64
+		LTDC_LEF_ENABLE						// Layer configuration flags
65
+	}
66
+#else
48 67
 	LTDC_UNUSED_LAYER_CONFIG
68
+#endif
49 69
 };
50 70
 
51 71
 #include "ili9341.h"
@@ -146,45 +166,39 @@ static void Init9341(GDisplay *g) {
146 166
 }
147 167
 
148 168
 static void init_board(GDisplay *g) {
169
+	(void) g;
149 170
 
150
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
151
-	g->board = 0;
152
-
153
-	switch(g->controllerdisplay) {
154
-	case 0:											// Set up for Display 0
155
-		palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7));		// UART_TX
156
-		palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7));	// UART_RX
157
-		palSetPadMode(GPIOF, GPIOF_LCD_DCX, PAL_MODE_ALTERNATE(5));
158
-		palSetPadMode(GPIOF, GPIOF_LCD_DE, PAL_MODE_ALTERNATE(14));
171
+	palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7));		// UART_TX
172
+	palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7));	// UART_RX
173
+	palSetPadMode(GPIOF, GPIOF_LCD_DCX, PAL_MODE_ALTERNATE(5));
174
+	palSetPadMode(GPIOF, GPIOF_LCD_DE, PAL_MODE_ALTERNATE(14));
159 175
 
160
-		#define STM32_SAISRC_NOCLOCK    (0 << 23)   /**< No clock.                  */
161
-		#define STM32_SAISRC_PLL        (1 << 23)   /**< SAI_CKIN is PLL.           */
162
-		#define STM32_SAIR_DIV2         (0 << 16)   /**< R divided by 2.            */
163
-		#define STM32_SAIR_DIV4         (1 << 16)   /**< R divided by 4.            */
164
-		#define STM32_SAIR_DIV8         (2 << 16)   /**< R divided by 8.            */
165
-		#define STM32_SAIR_DIV16        (3 << 16)   /**< R divided by 16.           */
176
+	#define STM32_SAISRC_NOCLOCK    (0 << 23)   /**< No clock.                  */
177
+	#define STM32_SAISRC_PLL        (1 << 23)   /**< SAI_CKIN is PLL.           */
178
+	#define STM32_SAIR_DIV2         (0 << 16)   /**< R divided by 2.            */
179
+	#define STM32_SAIR_DIV4         (1 << 16)   /**< R divided by 4.            */
180
+	#define STM32_SAIR_DIV8         (2 << 16)   /**< R divided by 8.            */
181
+	#define STM32_SAIR_DIV16        (3 << 16)   /**< R divided by 16.           */
166 182
 
167
-		#define STM32_PLLSAIN_VALUE                 192
168
-		#define STM32_PLLSAIQ_VALUE                 7
169
-		#define STM32_PLLSAIR_VALUE                 4
170
-		#define STM32_PLLSAIR_POST                  STM32_SAIR_DIV4
183
+	#define STM32_PLLSAIN_VALUE                 192
184
+	#define STM32_PLLSAIQ_VALUE                 7
185
+	#define STM32_PLLSAIR_VALUE                 4
186
+	#define STM32_PLLSAIR_POST                  STM32_SAIR_DIV4
171 187
 
172
-		/* PLLSAI activation.*/
173
-		RCC->PLLSAICFGR = (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24);
174
-		RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | STM32_PLLSAIR_POST;
175
-		RCC->CR |= RCC_CR_PLLSAION;
188
+	/* PLLSAI activation.*/
189
+	RCC->PLLSAICFGR = (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24);
190
+	RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | STM32_PLLSAIR_POST;
191
+	RCC->CR |= RCC_CR_PLLSAION;
176 192
 
177
-		// Initialise the SDRAM
178
-		SDRAM_Init();
193
+	// Initialise the SDRAM
194
+	SDRAM_Init();
179 195
 
180
-		// Clear the SDRAM
181
-		memset((void *)SDRAM_BANK_ADDR, 0, 0x400000);
196
+	// Clear the SDRAM
197
+	memset((void *)SDRAM_BANK_ADDR, 0, 0x400000);
182 198
 
183
-		spiStart(SPI_PORT, &spi_cfg);
199
+	spiStart(SPI_PORT, &spi_cfg);
184 200
 
185
-		Init9341(g);
186
-		break;
187
-	}
201
+	Init9341(g);
188 202
 }
189 203
 
190 204
 static GFXINLINE void post_init_board(GDisplay *g) {

+ 44 - 31
boards/base/STM32F439i-Eval/CubeHal/board_STM32LTDC.h

@@ -17,6 +17,8 @@
17 17
 #include "stm32f4xx_hal.h"
18 18
 #include "stm324x9i_eval_sdram.h"
19 19
 
20
+#define ALLOW_2ND_LAYER		TRUE
21
+
20 22
 // Panel parameters
21 23
 // This panel is a AMPIRE640480 panel.
22 24
 
@@ -35,8 +37,8 @@ static const ltdcConfig driverCfg = {
35 37
 		LTDC_PIXELFORMAT,					// Pixel format
36 38
 		0, 0,								// Start pixel position (x, y)
37 39
 		640, 480,							// Size of virtual layer (cx, cy)
38
-		LTDC_COLOR_FUCHSIA,					// Default color (ARGB8888)
39
-		0x980088,							// Color key (RGB888)
40
+		0x00000000,							// Default color (ARGB8888)
41
+		0x000000,							// Color key (RGB888)
40 42
 		LTDC_BLEND_FIX1_FIX2,				// Blending factors
41 43
 		0,									// Palette (RGB888, can be NULL)
42 44
 		0,									// Palette length
@@ -44,7 +46,25 @@ static const ltdcConfig driverCfg = {
44 46
 		LTDC_LEF_ENABLE						// Layer configuration flags
45 47
 	},
46 48
 
47
-	LTDC_UNUSED_LAYER_CONFIG				// Foreground layer config
49
+#if ALLOW_2ND_LAYER
50
+	{										// Foreground layer config (if turned on)
51
+		(LLDCOLOR_TYPE *)(SDRAM_DEVICE_ADDR+(640 * 480 * LTDC_PIXELBYTES)), // Frame buffer address
52
+		640, 480,							// Width, Height (pixels)
53
+		640 * LTDC_PIXELBYTES,				// Line pitch (bytes)
54
+		LTDC_PIXELFORMAT,					// Pixel format
55
+		0, 0,								// Start pixel position (x, y)
56
+		640, 480,							// Size of virtual layer (cx, cy)
57
+		0x00000000,							// Default color (ARGB8888)
58
+		0x000000,							// Color key (RGB888)
59
+		LTDC_BLEND_MOD1_MOD2,				// Blending factors
60
+		0,									// Palette (RGB888, can be NULL)
61
+		0,									// Palette length
62
+		0xFF,								// Constant alpha factor
63
+		LTDC_LEF_ENABLE						// Layer configuration flags
64
+	}
65
+#else
66
+	LTDC_UNUSED_LAYER_CONFIG
67
+#endif
48 68
 };
49 69
 
50 70
 // LCD Clock values
@@ -56,10 +76,10 @@ static void configureLcdClock(void)
56 76
 {
57 77
 	#if 1
58 78
 		RCC_PeriphCLKInitTypeDef	periph_clk_init_struct;
59
-		
79
+
60 80
 		periph_clk_init_struct.PLLSAI.PLLSAIN = LCD_PLLSAIN_VALUE;
61
-		periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;    
62
-		periph_clk_init_struct.PLLSAI.PLLSAIR = LCD_PLLSAIR_VALUE;    
81
+		periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
82
+		periph_clk_init_struct.PLLSAI.PLLSAIR = LCD_PLLSAIR_VALUE;
63 83
 		periph_clk_init_struct.PLLSAIDivR = LCD_PLLSAIDIVR_VALUE;
64 84
 		HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct);
65 85
 	#else
@@ -77,59 +97,52 @@ static void configureLcdPins(void)
77 97
 	GPIO_InitTypeDef			GPIO_Init_Structure;
78 98
 
79 99
 	// Enable peripheral clocks
80
-	__GPIOI_CLK_ENABLE(); 
100
+	__GPIOI_CLK_ENABLE();
81 101
 	__GPIOJ_CLK_ENABLE();
82
-	__GPIOK_CLK_ENABLE(); 
102
+	__GPIOK_CLK_ENABLE();
83 103
 
84 104
 	/*** LTDC Pins configuration ***/
85 105
 	// GPIOI
86
-	GPIO_Init_Structure.Pin       = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; 
106
+	GPIO_Init_Structure.Pin       = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
87 107
 	GPIO_Init_Structure.Mode      = GPIO_MODE_AF_PP;
88 108
 	GPIO_Init_Structure.Pull      = GPIO_NOPULL;
89 109
 	GPIO_Init_Structure.Speed     = GPIO_SPEED_FAST;
90
-	GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;  
110
+	GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;
91 111
 	HAL_GPIO_Init(GPIOI, &GPIO_Init_Structure);
92 112
 
93
-	// GPIOJ  
113
+	// GPIOJ
94 114
 	GPIO_Init_Structure.Pin       = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
95 115
 	                                GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | \
96 116
 	                                GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | \
97
-	                                GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; 
117
+	                                GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
98 118
 	GPIO_Init_Structure.Mode      = GPIO_MODE_AF_PP;
99 119
 	GPIO_Init_Structure.Pull      = GPIO_NOPULL;
100 120
 	GPIO_Init_Structure.Speed     = GPIO_SPEED_FAST;
101
-	GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;  
102
-	HAL_GPIO_Init(GPIOJ, &GPIO_Init_Structure);  
121
+	GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;
122
+	HAL_GPIO_Init(GPIOJ, &GPIO_Init_Structure);
103 123
 
104
-	// GPIOK configuration 
124
+	// GPIOK configuration
105 125
 	GPIO_Init_Structure.Pin       = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
106
-	                                GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; 
126
+	                                GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
107 127
 	GPIO_Init_Structure.Mode      = GPIO_MODE_AF_PP;
108 128
 	GPIO_Init_Structure.Pull      = GPIO_NOPULL;
109 129
 	GPIO_Init_Structure.Speed     = GPIO_SPEED_FAST;
110
-	GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;  
130
+	GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;
111 131
 	HAL_GPIO_Init(GPIOK, &GPIO_Init_Structure);
112 132
 }
113 133
 
114 134
 static GFXINLINE void init_board(GDisplay* g)
115 135
 {
116
-	// As we are not using multiple displays we set g->board to NULL as we don't use it
117
-	g->board = 0;
118
-
119
-	switch(g->controllerdisplay) {
120
-		case 0:
136
+	(void) g;
121 137
 
122
-		// Set LCD pixel clock rate
123
-		configureLcdClock();
124
-		
125
-		// Set pin directions
126
-		configureLcdPins();
138
+	// Set LCD pixel clock rate
139
+	configureLcdClock();
127 140
 
128
-		// Initialise the SDRAM
129
-		BSP_SDRAM_Init();
141
+	// Set pin directions
142
+	configureLcdPins();
130 143
 
131
-		break;
132
-	}
144
+	// Initialise the SDRAM
145
+	BSP_SDRAM_Init();
133 146
 }
134 147
 
135 148
 static GFXINLINE void post_init_board(GDisplay* g)

+ 53 - 39
boards/base/STM32F469i-Discovery/board_STM32LTDC.h

@@ -27,6 +27,8 @@
27 27
   static DSI_VidCfgTypeDef hdsivideo_handle;
28 28
   DSI_HandleTypeDef hdsi_eval;
29 29
 
30
+#define ALLOW_2ND_LAYER		FALSE			// Do we really have the RAM bandwidth for this?
31
+
30 32
 // Panel parameters
31 33
 // This panel is a KoD KM-040TMP-02-0621 DSI LCD Display.
32 34
 
@@ -45,8 +47,8 @@ static const ltdcConfig driverCfg = {
45 47
 		LTDC_PIXELFORMAT,					// Pixel format
46 48
 		0, 0,								// Start pixel position (x, y)
47 49
 		800, 480,							// Size of virtual layer (cx, cy)
48
-		LTDC_COLOR_FUCHSIA,					// Default color (ARGB8888)
49
-		0x980088,							// Color key (RGB888)
50
+		0x00000000,							// Default color (ARGB8888)
51
+		0x000000,							// Color key (RGB888)
50 52
 		LTDC_BLEND_FIX1_FIX2,				// Blending factors
51 53
 		0,									// Palette (RGB888, can be NULL)
52 54
 		0,									// Palette length
@@ -54,18 +56,34 @@ static const ltdcConfig driverCfg = {
54 56
 		LTDC_LEF_ENABLE						// Layer configuration flags
55 57
 	},
56 58
 
57
-	LTDC_UNUSED_LAYER_CONFIG				// Foreground layer config
59
+#if ALLOW_2ND_LAYER
60
+	{										// Foreground layer config (if turned on)
61
+		(LLDCOLOR_TYPE *)(SDRAM_DEVICE_ADDR+(800 * 480 * LTDC_PIXELBYTES)), // Frame buffer address
62
+		800, 480,							// Width, Height (pixels)
63
+		800 * LTDC_PIXELBYTES,				// Line pitch (bytes)
64
+		LTDC_PIXELFORMAT,					// Pixel format
65
+		0, 0,								// Start pixel position (x, y)
66
+		800, 480,							// Size of virtual layer (cx, cy)
67
+		0x00000000,							// Default color (ARGB8888)
68
+		0x000000,							// Color key (RGB888)
69
+		LTDC_BLEND_MOD1_MOD2,				// Blending factors
70
+		0,									// Palette (RGB888, can be NULL)
71
+		0,									// Palette length
72
+		0xFF,								// Constant alpha factor
73
+		LTDC_LEF_ENABLE						// Layer configuration flags
74
+	}
75
+#else
76
+	LTDC_UNUSED_LAYER_CONFIG
77
+#endif
58 78
 };
59 79
 
60 80
 /* Display timing */
61 81
 #define KoD_FREQUENCY_DIVIDER 7
62 82
 
63 83
 static GFXINLINE void init_board(GDisplay *g) {
84
+	(void) g;
64 85
 
65
-	// As we are not using multiple displays we set g->board to NULL as we don't use it
66
-	g->board = 0;
67
-
68
-	  DSI_PLLInitTypeDef dsiPllInit;
86
+	DSI_PLLInitTypeDef dsiPllInit;
69 87
   	DSI_PHY_TimerTypeDef  PhyTimings;
70 88
 //  	static RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;
71 89
   	uint32_t LcdClock  = 30000;//27429; /*!< LcdClk = 27429 kHz */
@@ -89,8 +107,8 @@ static GFXINLINE void init_board(GDisplay *g) {
89 107
   	uint32_t                   HBP; /*!< Horizontal Back Porch time in units of lcdClk */
90 108
   	uint32_t                   HFP; /*!< Horizontal Front Porch time in units of lcdClk */
91 109
   	uint32_t                   HACT; /*!< Horizontal Active time in units of lcdClk = imageSize X in pixels to display */
92
-  
93
-  
110
+
111
+
94 112
   	/* Toggle Hardware Reset of the DSI LCD using
95 113
   	* its XRES signal (active low) */
96 114
   	BSP_LCD_Reset();
@@ -102,19 +120,19 @@ static GFXINLINE void init_board(GDisplay *g) {
102 120
   	* - NVIC IRQ related to IP blocks enabled
103 121
   	*/
104 122
   	BSP_LCD_MspInit();
105
-  
106
-	/*************************DSI Initialization***********************************/  
107
-  
123
+
124
+	/*************************DSI Initialization***********************************/
125
+
108 126
   	/* Base address of DSI Host/Wrapper registers to be set before calling De-Init */
109 127
   	hdsi_eval.Instance = DSI;
110
-  
128
+
111 129
   	HAL_DSI_DeInit(&(hdsi_eval));
112
-  
130
+
113 131
 	#if !defined(USE_STM32469I_DISCO_REVA)
114 132
   		dsiPllInit.PLLNDIV  = 125;
115 133
   		dsiPllInit.PLLIDF   = DSI_PLL_IN_DIV2;
116 134
   		dsiPllInit.PLLODF   = DSI_PLL_OUT_DIV1;
117
-	#else  
135
+	#else
118 136
   		dsiPllInit.PLLNDIV  = 100;
119 137
   		dsiPllInit.PLLIDF   = DSI_PLL_IN_DIV5;
120 138
   		dsiPllInit.PLLODF   = DSI_PLL_OUT_DIV1;
@@ -123,10 +141,10 @@ static GFXINLINE void init_board(GDisplay *g) {
123 141
 
124 142
   	/* Set number of Lanes */
125 143
   	hdsi_eval.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
126
-  
144
+
127 145
   	/* TXEscapeCkdiv = f(LaneByteClk)/15.62 = 4 */
128
-  	hdsi_eval.Init.TXEscapeCkdiv = laneByteClk_kHz/15620; 
129
-  
146
+  	hdsi_eval.Init.TXEscapeCkdiv = laneByteClk_kHz/15620;
147
+
130 148
   	HAL_DSI_Init(&(hdsi_eval), &(dsiPllInit));
131 149
 
132 150
   	/* Timing parameters for all Video modes
@@ -139,7 +157,7 @@ static GFXINLINE void init_board(GDisplay *g) {
139 157
 
140 158
   	HACT = lcd_x_size;
141 159
   	VACT = lcd_y_size;
142
-  
160
+
143 161
   	/* The following values are same for portrait and landscape orientations */
144 162
   	VSA  = 12;//OTM8009A_480X800_VSYNC;        /* 12  */
145 163
   	VBP  = 12;//OTM8009A_480X800_VBP;          /* 12  */
@@ -152,11 +170,11 @@ static GFXINLINE void init_board(GDisplay *g) {
152 170
   	hdsivideo_handle.ColorCoding = LCD_DSI_PIXEL_DATA_FMT_RBG888;
153 171
   	hdsivideo_handle.VSPolarity = DSI_VSYNC_ACTIVE_HIGH;
154 172
   	hdsivideo_handle.HSPolarity = DSI_HSYNC_ACTIVE_HIGH;
155
-  	hdsivideo_handle.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;  
173
+  	hdsivideo_handle.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
156 174
   	hdsivideo_handle.Mode = DSI_VID_MODE_BURST; /* Mode Video burst ie : one LgP per line */
157 175
   	hdsivideo_handle.NullPacketSize = 0xFFF;
158 176
   	hdsivideo_handle.NumberOfChunks = 0;
159
-  	hdsivideo_handle.PacketSize                = HACT; /* Value depending on display orientation choice portrait/landscape */ 
177
+  	hdsivideo_handle.PacketSize                = HACT; /* Value depending on display orientation choice portrait/landscape */
160 178
   	hdsivideo_handle.HorizontalSyncActive      = (HSA * laneByteClk_kHz) / LcdClock;
161 179
   	hdsivideo_handle.HorizontalBackPorch       = (HBP * laneByteClk_kHz) / LcdClock;
162 180
   	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) {
164 182
   	hdsivideo_handle.VerticalBackPorch         = VBP;
165 183
   	hdsivideo_handle.VerticalFrontPorch        = VFP;
166 184
   	hdsivideo_handle.VerticalActive            = VACT; /* Value depending on display orientation choice portrait/landscape */
167
-  
185
+
168 186
   	/* Enable or disable sending LP command while streaming is active in video mode */
169 187
   	hdsivideo_handle.LPCommandEnable = DSI_LP_COMMAND_ENABLE; /* Enable sending commands in mode LP (Low Power) */
170
-  
188
+
171 189
   	/* Largest packet size possible to transmit in LP mode in VSA, VBP, VFP regions */
172 190
   	/* Only useful when sending LP packets is allowed while streaming is active in video mode */
173 191
   	hdsivideo_handle.LPLargestPacketSize = 16;
@@ -184,7 +202,7 @@ static GFXINLINE void init_board(GDisplay *g) {
184 202
   	hdsivideo_handle.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE;   /* Allow sending LP commands during VFP period */
185 203
   	hdsivideo_handle.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE;   /* Allow sending LP commands during VBP period */
186 204
   	hdsivideo_handle.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; /* Allow sending LP commands during VSync = VSA period */
187
-  
205
+
188 206
   	/* Configure DSI Video mode timings with settings set above */
189 207
   	HAL_DSI_ConfigVideoMode(&(hdsi_eval), &(hdsivideo_handle));
190 208
 
@@ -197,7 +215,7 @@ static GFXINLINE void init_board(GDisplay *g) {
197 215
   	PhyTimings.StopWaitTime = 10;
198 216
   	HAL_DSI_ConfigPhyTimer(&hdsi_eval, &PhyTimings);
199 217
 
200
-	/*************************End DSI Initialization*******************************/ 
218
+	/*************************End DSI Initialization*******************************/
201 219
 
202 220
   /************************LTDC Initialization***********************************/
203 221
 
@@ -241,32 +259,28 @@ static GFXINLINE void init_board(GDisplay *g) {
241 259
     /* Initialize the SDRAM */
242 260
     BSP_SDRAM_Init();
243 261
   #endif /* DATA_IN_ExtSDRAM */
262
+
244 263
 }
245 264
 
246 265
 static GFXINLINE void post_init_board(GDisplay* g)
247 266
 {
248 267
 	(void)g;
249
-  
268
+
269
+	if (g->controllerdisplay)
270
+		return;
271
+
250 272
   	/* Initialize the font */
251 273
   	BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
252
-  
274
+
253 275
 	/************************End LTDC Initialization*******************************/
254
-		
255
-		
256
-	/***********************OTM8009A Initialization********************************/  
257
-  
276
+
277
+
278
+	/***********************OTM8009A Initialization********************************/
279
+
258 280
   	/* Initialize the OTM8009A LCD Display IC Driver (KoD LCD IC Driver)
259 281
   	*  depending on configuration set in 'hdsivideo_handle'.
260 282
   	*/
261 283
   	OTM8009A_Init(OTM8009A_FORMAT_RGB888, OTM8009A_ORIENTATION_LANDSCAPE);
262
-  
263
-	/***********************End OTM8009A Initialization****************************/ 
264
-
265
-	// ------------------------------------------------------------------------
266
-
267
-	//BSP_LCD_LayerDefaultInit(LTDC_ACTIVE_LAYER_BACKGROUND, LCD_FB_START_ADDRESS);
268
-	//BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER_BACKGROUND);
269
-	//BSP_LCD_SetLayerVisible(LTDC_ACTIVE_LAYER_FOREGROUND, DISABLE);
270 284
 }
271 285
 
272 286
 static GFXINLINE void set_backlight(GDisplay* g, uint8_t percent)

+ 87 - 78
boards/base/STM32F746-Discovery/board_STM32LTDC.h

@@ -36,6 +36,8 @@
36 36
 	#define AFRH	AFR[1]
37 37
 #endif
38 38
 
39
+#define ALLOW_2ND_LAYER		TRUE
40
+
39 41
 static const ltdcConfig driverCfg = {
40 42
 	480, 272,								// Width, Height (pixels)
41 43
 	41, 10,									// Horizontal, Vertical sync (pixels)
@@ -51,8 +53,8 @@ static const ltdcConfig driverCfg = {
51 53
 		LTDC_PIXELFORMAT,					// Pixel format
52 54
 		0, 0,								// Start pixel position (x, y)
53 55
 		480, 272,							// Size of virtual layer (cx, cy)
54
-		LTDC_COLOR_FUCHSIA,					// Default color (ARGB8888)
55
-		0x980088,							// Color key (RGB888)
56
+		0x00000000,							// Default color (ARGB8888)
57
+		0x000000,							// Color key (RGB888)
56 58
 		LTDC_BLEND_FIX1_FIX2,				// Blending factors
57 59
 		0,									// Palette (RGB888, can be NULL)
58 60
 		0,									// Palette length
@@ -60,7 +62,25 @@ static const ltdcConfig driverCfg = {
60 62
 		LTDC_LEF_ENABLE						// Layer configuration flags
61 63
 	},
62 64
 
63
-	LTDC_UNUSED_LAYER_CONFIG				// Foreground layer config
65
+#if ALLOW_2ND_LAYER
66
+	{										// Foreground layer config (if turned on)
67
+		(LLDCOLOR_TYPE *)(SDRAM_DEVICE_ADDR+(480 * 272 * LTDC_PIXELBYTES)), // Frame buffer address
68
+		480, 272,							// Width, Height (pixels)
69
+		480 * LTDC_PIXELBYTES,				// Line pitch (bytes)
70
+		LTDC_PIXELFORMAT,					// Pixel format
71
+		0, 0,								// Start pixel position (x, y)
72
+		480, 272,							// Size of virtual layer (cx, cy)
73
+		0x00000000,							// Default color (ARGB8888)
74
+		0x000000,							// Color key (RGB888)
75
+		LTDC_BLEND_MOD1_MOD2,				// Blending factors
76
+		0,									// Palette (RGB888, can be NULL)
77
+		0,									// Palette length
78
+		0xFF,								// Constant alpha factor
79
+		LTDC_LEF_ENABLE						// Layer configuration flags
80
+	}
81
+#else
82
+	LTDC_UNUSED_LAYER_CONFIG
83
+#endif
64 84
 };
65 85
 
66 86
 static void configureLcdPins(void) {
@@ -97,10 +117,10 @@ static void configureLcdPins(void) {
97 117
 		palSetPadMode(GPIOI, GPIOI_LCD_DISP,	PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);	// PI12: LCD_DISP_PIN
98 118
 		palSetPadMode(GPIOK, GPIOK_LCD_BL_CTRL,	PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);	// PK3 : LCD_BL_CTRL
99 119
 	#else
100
-	
120
+
101 121
 		//-------------------------------------------
102 122
 		// Initialise port PE
103
-		
123
+
104 124
 		RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;
105 125
 		GPIOE->MODER |= (
106 126
 						  GPIO_MODER_MODER4_1							// PE4:  LCD_B0 - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(14)
@@ -123,7 +143,7 @@ static void configureLcdPins(void) {
123 143
 
124 144
 		//-------------------------------------------
125 145
 		// Initialise port PG
126
-		
146
+
127 147
 		RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
128 148
 		GPIOG->MODER |= (
129 149
 						  GPIO_MODER_MODER12_1							// PG12:  LCD_B4 - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(9)
@@ -143,10 +163,10 @@ static void configureLcdPins(void) {
143 163
 		GPIOG->AFRH |= (
144 164
 						  ( 9U << 4*(12-8))
145 165
 						);
146
-	
166
+
147 167
 		//-------------------------------------------
148 168
 		// Initialise port PI
149
-		
169
+
150 170
 		RCC->AHB1ENR |= RCC_AHB1ENR_GPIOIEN;
151 171
 		GPIOI->MODER |= (
152 172
 						  GPIO_MODER_MODER9_1							// PI9:  LCD_VSYNC    - PAL_STM32_OSPEED_HIGHEST, PAL_MODE_ALTERNATE(14)
@@ -374,77 +394,66 @@ static void configureLcdPins(void) {
374 394
 }
375 395
 
376 396
 static GFXINLINE void init_board(GDisplay *g) {
397
+	(void) g;
377 398
 
378
-	// As we are not using multiple displays we set g->board to NULL as we don't use it
379
-	g->board = 0;
380
-
381
-	switch(g->controllerdisplay) {
382
-	case 0:
383
-
384
-		// Set pin directions
385
-		configureLcdPins();
386
-
387
-		// Enable the display and turn on the backlight
388
-		#if GFX_USE_OS_CHIBIOS && !GFX_LTDC_USE_DIRECTIO
389
-		    palSetPad(GPIOI, GPIOI_LCD_DISP);
390
-		    palSetPad(GPIOK, GPIOK_LCD_BL_CTRL);
391
-		#else
392
-		    GPIOI->ODR |= (1 << 12);  // PowerOn
393
-		    GPIOK->ODR |= (1 << 3);   // Backlight on
394
-		#endif
395
-
396
-		#if GFX_LTDC_TIMING_SET != 0
397
-				#define STM32_SAISRC_NOCLOCK    (0 << 23)   /**< No clock.                  */
398
-				#define STM32_SAISRC_PLL        (1 << 23)   /**< SAI_CKIN is PLL.           */
399
-				#define STM32_SAIR_DIV2         (0 << 16)   /**< R divided by 2.            */
400
-				#define STM32_SAIR_DIV4         (1 << 16)   /**< R divided by 4.            */
401
-				#define STM32_SAIR_DIV8         (2 << 16)   /**< R divided by 8.            */
402
-				#define STM32_SAIR_DIV16        (3 << 16)   /**< R divided by 16.           */
403
-
404
-				// Some operating systems get these wrong eg ChibiOS - define our own values
405
-				#undef STM32_PLLSAIN_VALUE
406
-				#undef STM32_PLLSAIQ_VALUE
407
-				#undef STM32_PLLSAIP_VALUE
408
-				#undef STM32_PLLSAIR_VALUE
409
-
410
-				/* Display timing */
411
-				// RK043FN48H LCD clock configuration
412
-				// PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz
413
-				// PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz
414
-				// PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz
415
-				// LTDC clock frequency = PLLLCDCLK / STM32_PLLSAIR_POST = 38.4/4 = 9.6Mhz
416
-				#if GFX_LTDC_TIMING_SET == 1
417
-					#define RK043FN48H_FREQUENCY_DIVIDER		5
418
-					#define STM32_PLLSAIN_VALUE                 192
419
-					#define STM32_PLLSAIQ_VALUE                 4
420
-					#define STM32_PLLSAIP_VALUE					4
421
-					#define STM32_PLLSAIR_VALUE                 RK043FN48H_FREQUENCY_DIVIDER
422
-					#define STM32_PLLSAIR_POST                  STM32_SAIR_DIV4
423
-				#elif  GFX_LTDC_TIMING_SET == 2
424
-					#define RK043FN48H_FREQUENCY_DIVIDER		4
425
-					#define STM32_PLLSAIN_VALUE                 192
426
-					#define STM32_PLLSAIQ_VALUE                 4
427
-					#define STM32_PLLSAIP_VALUE					4
428
-					#define STM32_PLLSAIR_VALUE                 RK043FN48H_FREQUENCY_DIVIDER
429
-					#define STM32_PLLSAIR_POST                  STM32_SAIR_DIV4
430
-				#else
431
-					#error "LTDC: - Unknown timing set for the STM32F746-Discovery board"
432
-				#endif
433
-				
434
-				RCC->CR &= ~RCC_CR_PLLSAION;
435
-				RCC->PLLSAICFGR = ((STM32_PLLSAIP_VALUE/2-1)<<16) | (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24);
436
-				RCC->DCKCFGR1 = (RCC->DCKCFGR1 & ~RCC_DCKCFGR1_PLLSAIDIVR) | STM32_PLLSAIR_POST;
437
-				RCC->CR |= RCC_CR_PLLSAION;
438
-		#endif
439
-
440
-		// Initialise the SDRAM
441
-		BSP_SDRAM_Init();
442
-
443
-		// Clear the SDRAM
444
-		//memset((void *)SDRAM_BANK_ADDR, 0, 0x400000);
445
-
446
-		break;
447
-	}
399
+	// Set pin directions
400
+	configureLcdPins();
401
+
402
+	// Enable the display and turn on the backlight
403
+	#if GFX_USE_OS_CHIBIOS && !GFX_LTDC_USE_DIRECTIO
404
+	    palSetPad(GPIOI, GPIOI_LCD_DISP);
405
+	    palSetPad(GPIOK, GPIOK_LCD_BL_CTRL);
406
+	#else
407
+	    GPIOI->ODR |= (1 << 12);  // PowerOn
408
+	    GPIOK->ODR |= (1 << 3);   // Backlight on
409
+	#endif
410
+
411
+	#if GFX_LTDC_TIMING_SET != 0
412
+			#define STM32_SAISRC_NOCLOCK    (0 << 23)   /**< No clock.                  */
413
+			#define STM32_SAISRC_PLL        (1 << 23)   /**< SAI_CKIN is PLL.           */
414
+			#define STM32_SAIR_DIV2         (0 << 16)   /**< R divided by 2.            */
415
+			#define STM32_SAIR_DIV4         (1 << 16)   /**< R divided by 4.            */
416
+			#define STM32_SAIR_DIV8         (2 << 16)   /**< R divided by 8.            */
417
+			#define STM32_SAIR_DIV16        (3 << 16)   /**< R divided by 16.           */
418
+
419
+			// Some operating systems get these wrong eg ChibiOS - define our own values
420
+			#undef STM32_PLLSAIN_VALUE
421
+			#undef STM32_PLLSAIQ_VALUE
422
+			#undef STM32_PLLSAIP_VALUE
423
+			#undef STM32_PLLSAIR_VALUE
424
+
425
+			/* Display timing */
426
+			// RK043FN48H LCD clock configuration
427
+			// PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz
428
+			// PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz
429
+			// PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz
430
+			// LTDC clock frequency = PLLLCDCLK / STM32_PLLSAIR_POST = 38.4/4 = 9.6Mhz
431
+			#if GFX_LTDC_TIMING_SET == 1
432
+				#define RK043FN48H_FREQUENCY_DIVIDER		5
433
+				#define STM32_PLLSAIN_VALUE                 192
434
+				#define STM32_PLLSAIQ_VALUE                 4
435
+				#define STM32_PLLSAIP_VALUE					4
436
+				#define STM32_PLLSAIR_VALUE                 RK043FN48H_FREQUENCY_DIVIDER
437
+				#define STM32_PLLSAIR_POST                  STM32_SAIR_DIV4
438
+			#elif  GFX_LTDC_TIMING_SET == 2
439
+				#define RK043FN48H_FREQUENCY_DIVIDER		4
440
+				#define STM32_PLLSAIN_VALUE                 192
441
+				#define STM32_PLLSAIQ_VALUE                 4
442
+				#define STM32_PLLSAIP_VALUE					4
443
+				#define STM32_PLLSAIR_VALUE                 RK043FN48H_FREQUENCY_DIVIDER
444
+				#define STM32_PLLSAIR_POST                  STM32_SAIR_DIV4
445
+			#else
446
+				#error "LTDC: - Unknown timing set for the STM32F746-Discovery board"
447
+			#endif
448
+
449
+			RCC->CR &= ~RCC_CR_PLLSAION;
450
+			RCC->PLLSAICFGR = ((STM32_PLLSAIP_VALUE/2-1)<<16) | (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24);
451
+			RCC->DCKCFGR1 = (RCC->DCKCFGR1 & ~RCC_DCKCFGR1_PLLSAIDIVR) | STM32_PLLSAIR_POST;
452
+			RCC->CR |= RCC_CR_PLLSAION;
453
+	#endif
454
+
455
+	// Initialise the SDRAM
456
+	BSP_SDRAM_Init();
448 457
 }
449 458
 
450 459
 static GFXINLINE void post_init_board(GDisplay* g) {

+ 9 - 0
changelog.txt

@@ -51,6 +51,15 @@ FEATURE:	Added gwinTextEditSendKey() and gwinTextEditSendSpecialKey()
51 51
 FEATURE:	Implemented the JPG image decoder
52 52
 FEATURE:	Added SSD1322 driver
53 53
 FEATURE:    Added support for Zephyr operating system
54
+FEATURE:	STM32LTDC driver now supports using both layers as seperate displays. The 2nd display is the foreground layer
55
+CHANGE:		STM32LTDC driver now uses RGB888 pixel format by default
56
+FEATURE:	Added GDISP_LTDC_USE_RGB565 config variable to force STM32LTDC driver to use RGB565 pixel format
57
+FEATURE:	The STM32LTDC 2nd display (the foreground layer) supports alpha.
58
+FEATURE:	The STM32 board files for known boards have been updated to contain support for the 2nd layer.
59
+FEATURE:	Added AHTML2COLOR() and ARGB2COLOR() to support alpha. This is currently only supported for the RGB888 pixel format.
60
+FEATURE:	Added the new color GFXTRANSPARENT - only available for RGB888 pixel format on alpha capable displays.
61
+NOTE:		Alpha support in RGB888 requies an alpha capable display (STM32LTDC 2nd display only currently)
62
+NOTE:		Alpha support in RGB888 is NOT the standard ARGB8888 format. Only use AHTML2COLOR() and ARGB2COLOR() to create alpha colors.
54 63
 
55 64
 
56 65
 *** Release 2.7 ***

+ 1 - 1
demos/modules/gdisp/multiple_displays/gfxconf.h

@@ -84,7 +84,7 @@
84 84
 	//#define GDISP_PIXELFORMAT     GDISP_PIXELFORMAT_RGB888
85 85
 
86 86
 #elif !defined(GDISP_TOTAL_DISPLAYS) && (!defined(GDISP_PIXELFORMAT) || !defined(GDISP_DRIVER_LIST))
87
-	#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"
87
+	#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"
88 88
 #endif
89 89
 
90 90
 /*

+ 34 - 13
drivers/gdisp/STM32LTDC/board_STM32LTDC_template.h

@@ -8,6 +8,8 @@
8 8
 #ifndef _GDISP_LLD_BOARD_H
9 9
 #define _GDISP_LLD_BOARD_H
10 10
 
11
+#define ALLOW_2ND_LAYER		TRUE
12
+
11 13
 static const ltdcConfig driverCfg = {
12 14
 	480, 272,								// Width, Height (pixels)
13 15
 	41, 10,									// Horizontal, Vertical sync (pixels)
@@ -17,14 +19,14 @@ static const ltdcConfig driverCfg = {
17 19
 	0x000000,								// Clear color (RGB888)
18 20
 
19 21
 	{										// Background layer config
20
-		(LLDCOLOR_TYPE *)SDRAM_DEVICE_ADDR,	// Frame buffer address
22
+		(LLDCOLOR_TYPE *)SDRAM_DEVICE_ADDR, // Frame buffer address
21 23
 		480, 272,							// Width, Height (pixels)
22 24
 		480 * LTDC_PIXELBYTES,				// Line pitch (bytes)
23 25
 		LTDC_PIXELFORMAT,					// Pixel format
24 26
 		0, 0,								// Start pixel position (x, y)
25 27
 		480, 272,							// Size of virtual layer (cx, cy)
26
-		LTDC_COLOR_FUCHSIA,					// Default color (ARGB8888)
27
-		0x980088,							// Color key (RGB888)
28
+		0x00000000,							// Default color (ARGB8888)
29
+		0x000000,							// Color key (RGB888)
28 30
 		LTDC_BLEND_FIX1_FIX2,				// Blending factors
29 31
 		0,									// Palette (RGB888, can be NULL)
30 32
 		0,									// Palette length
@@ -32,28 +34,47 @@ static const ltdcConfig driverCfg = {
32 34
 		LTDC_LEF_ENABLE						// Layer configuration flags
33 35
 	},
34 36
 
35
-	LTDC_UNUSED_LAYER_CONFIG				// Foreground layer config
37
+#if ALLOW_2ND_LAYER
38
+	{										// Foreground layer config (if turned on)
39
+		(LLDCOLOR_TYPE *)(SDRAM_DEVICE_ADDR+(480 * 272 * LTDC_PIXELBYTES)), // Frame buffer address
40
+		480, 272,							// Width, Height (pixels)
41
+		480 * LTDC_PIXELBYTES,				// Line pitch (bytes)
42
+		LTDC_PIXELFORMAT,					// Pixel format
43
+		0, 0,								// Start pixel position (x, y)
44
+		480, 272,							// Size of virtual layer (cx, cy)
45
+		0x00000000,							// Default color (ARGB8888)
46
+		0x000000,							// Color key (RGB888)
47
+		LTDC_BLEND_MOD1_MOD2,				// Blending factors
48
+		0,									// Palette (RGB888, can be NULL)
49
+		0,									// Palette length
50
+		0xFF,								// Constant alpha factor
51
+		LTDC_LEF_ENABLE						// Layer configuration flags
52
+	}
53
+#else
54
+	LTDC_UNUSED_LAYER_CONFIG
55
+#endif
36 56
 };
37 57
 
38 58
 static GFXINLINE void init_board(GDisplay* g) {
39
-
40
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
41
-	g->board = 0;
42
-
43
-	switch(g->controllerdisplay) {
44
-	case 0:											// Set up for Display 0
45
-		// Your init here
46
-		break;
47
-	}
59
+	// This is function only called once with the display for the background layer.
60
+	(void)g;
48 61
 }
49 62
 
50 63
 static GFXINLINE void post_init_board(GDisplay* g)
51 64
 {
65
+	// This is function may be called twice - once for the background display and once
66
+	// for the foreground display.
67
+	// Note: It doesn't get called for the foreground display unless gfxconf.h has been
68
+	//		setup for two displays on this controller.
52 69
 	(void)g;
53 70
 }
54 71
 
55 72
 static GFXINLINE void set_backlight(GDisplay* g, uint8_t percent)
56 73
 {
74
+	// This is function may be called with the display for either the foreground
75
+	// or the background layer.
76
+	// Note: It can't be called for the foreground display unless gfxconf.h has been
77
+	//		setup for two displays on this controller.
57 78
 	(void)g;
58 79
 	(void)percent;
59 80
 }

+ 84 - 50
drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c

@@ -99,13 +99,15 @@ typedef struct ltdcConfig {
99 99
 /* Driver local routines.                                                    */
100 100
 /*===========================================================================*/
101 101
 
102
-#define PIXIL_POS(g, x, y)		((y) * driverCfg.bglayer.pitch + (x) * LTDC_PIXELBYTES)
103
-#define PIXEL_ADDR(g, pos)		((LLDCOLOR_TYPE *)((uint8_t *)driverCfg.bglayer.frame+pos))
102
+#define PIXIL_POS(g, x, y)		((y) * ((ltdcLayerConfig *)g->priv)->pitch + (x) * LTDC_PIXELBYTES)
103
+#define PIXEL_ADDR(g, pos)		((LLDCOLOR_TYPE *)((uint8_t *)((ltdcLayerConfig *)g->priv)->frame+pos))
104 104
 
105 105
 /*===========================================================================*/
106 106
 /* Driver exported functions.                                                */
107 107
 /*===========================================================================*/
108 108
 
109
+static const ltdcLayerConfig layerOff = LTDC_UNUSED_LAYER_CONFIG;
110
+
109 111
 static void _ltdc_reload(void) {
110 112
 	LTDC->SRCR |= LTDC_SRCR_IMR;
111 113
 	while (LTDC->SRCR & (LTDC_SRCR_IMR | LTDC_SRCR_VBR))
@@ -210,7 +212,7 @@ static void _ltdc_init(void) {
210 212
 	_ltdc_layer_init(LTDC_Layer1, &driverCfg.bglayer);
211 213
 
212 214
 	// Load the foreground layer
213
-	_ltdc_layer_init(LTDC_Layer2, &driverCfg.fglayer);
215
+	_ltdc_layer_init(LTDC_Layer2, &layerOff);
214 216
 
215 217
 	// Interrupt handling
216 218
 	// 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) {
227 229
 	g->priv = 0;
228 230
 	g->board = 0;
229 231
 
230
-	// Init the board
231
-	init_board(g);
232
+	switch(g->controllerdisplay) {
233
+	case 0:			// Display 0 is the background layer
234
+		// Init the board
235
+		init_board(g);
232 236
 
233
-	// Initialise the LTDC controller
234
-	_ltdc_init();
237
+		// Initialise the LTDC controller
238
+		_ltdc_init();
235 239
 
236
-	// Initialise DMA2D
237
-	#if LTDC_USE_DMA2D
238
-		dma2d_init();
239
-	#endif
240
+		// Initialise DMA2D
241
+		#if LTDC_USE_DMA2D
242
+			dma2d_init();
243
+		#endif
244
+
245
+		if (!(driverCfg.bglayer.layerflags & LTDC_LEF_ENABLE))
246
+			return FALSE;
247
+
248
+		g->priv = (void *)&driverCfg.bglayer;
249
+
250
+	    // Finish Init the board
251
+	    post_init_board(g);
252
+
253
+		// Turn on the back-light
254
+		set_backlight(g, GDISP_INITIAL_BACKLIGHT);
255
+
256
+		break;
257
+
258
+	case 1:			// Display 1 is the foreground layer
259
+
260
+		if (!(driverCfg.fglayer.layerflags & LTDC_LEF_ENABLE))
261
+			return FALSE;
240 262
 
241
-    // Finish Init the board
242
-    post_init_board(g);
263
+		// Load the foreground layer
264
+		_ltdc_layer_init(LTDC_Layer2, &driverCfg.fglayer);
265
+		_ltdc_reload();
243 266
 
244
-	// Turn on the back-light
245
-	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
267
+		g->priv = (void *)&driverCfg.fglayer;
268
+
269
+	    // Finish Init the board
270
+	    post_init_board(g);
271
+
272
+		break;
273
+
274
+	default:		// There is only 1 LTDC in the CPU and only the 2 layers in the LTDC.
275
+		return FALSE;
276
+	}
246 277
 
247 278
 	// Initialise the GDISP structure
248
-	g->g.Width = driverCfg.bglayer.width;
249
-	g->g.Height = driverCfg.bglayer.height;
279
+	g->g.Width = ((ltdcLayerConfig *)g->priv)->width;
280
+	g->g.Height = ((ltdcLayerConfig *)g->priv)->height;
250 281
 	g->g.Orientation = GDISP_ROTATE_0;
251 282
 	g->g.Powermode = powerOn;
252 283
 	g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
@@ -282,7 +313,14 @@ LLDSPEC void gdisp_lld_draw_pixel(GDisplay* g) {
282 313
 		while(DMA2D->CR & DMA2D_CR_START);
283 314
 	#endif
284 315
 
285
-	PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color);
316
+	#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
317
+		// As we don't support ARGB pixel types in uGFX yet we will
318
+		// use RGB with an inverted alpha value for compatibility
319
+		// ie. 0x00FFFFFF is fully opaque white, 0xFFFFFFFF is fully transparent white
320
+		PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color) ^ 0xFF000000;
321
+	#else
322
+		PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color);
323
+	#endif
286 324
 }
287 325
 
288 326
 LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay* g) {
@@ -313,27 +351,21 @@ LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay* g) {
313 351
 		while(DMA2D->CR & DMA2D_CR_START);
314 352
 	#endif
315 353
 
316
-	color = PIXEL_ADDR(g, pos)[0];
317
-	
354
+	#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
355
+		// As we don't support ARGB pixel types in uGFX yet we will
356
+		// use RGB with an inverted alpha value for compatibility
357
+		// ie. 0x00FFFFFF is fully opaque white, 0xFFFFFFFF is fully transparent white
358
+		color = PIXEL_ADDR(g, pos)[0] ^ 0xFF000000;
359
+	#else
360
+		color = PIXEL_ADDR(g, pos)[0];
361
+	#endif
362
+
318 363
 	return gdispNative2Color(color);
319 364
 }
320 365
 
321 366
 #if GDISP_NEED_CONTROL
322 367
 	LLDSPEC void gdisp_lld_control(GDisplay* g) {
323 368
 		switch(g->p.x) {
324
-		case GDISP_CONTROL_POWER:
325
-			if (g->g.Powermode == (powermode_t)g->p.ptr)
326
-				return;
327
-			switch((powermode_t)g->p.ptr) {
328
-			case powerOff: case powerOn: case powerSleep: case powerDeepSleep:
329
-				// TODO
330
-				break;
331
-			default:
332
-				return;
333
-			}
334
-			g->g.Powermode = (powermode_t)g->p.ptr;
335
-			return;
336
-
337 369
 		case GDISP_CONTROL_ORIENTATION:
338 370
 			if (g->g.Orientation == (orientation_t)g->p.ptr)
339 371
 				return;
@@ -369,12 +401,6 @@ LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay* g) {
369 401
 			set_backlight(g, (unsigned)g->p.ptr);
370 402
 			g->g.Backlight = (unsigned)g->p.ptr;
371 403
 			return;
372
-
373
-		case GDISP_CONTROL_CONTRAST:
374
-			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
375
-			// TODO
376
-			g->g.Contrast = (unsigned)g->p.ptr;
377
-			return;
378 404
 		}
379 405
 	}
380 406
 #endif
@@ -383,14 +409,14 @@ LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay* g) {
383 409
 	static void dma2d_init(void) {
384 410
 		// Enable DMA2D clock
385 411
 		RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
386
-	
412
+
387 413
 		// Output color format
388 414
 		#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
389 415
 			DMA2D->OPFCCR = OPFCCR_RGB565;
390 416
 		#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
391 417
 			DMA2D->OPFCCR = OPFCCR_ARGB8888;
392 418
 		#endif
393
-	
419
+
394 420
 		// Foreground color format
395 421
 		#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
396 422
 			DMA2D->FGPFCCR = FGPFCCR_CM_RGB565;
@@ -401,14 +427,11 @@ LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay* g) {
401 427
 
402 428
 	// Uses p.x,p.y  p.cx,p.cy  p.color
403 429
 	LLDSPEC void gdisp_lld_fill_area(GDisplay* g)
404
-	{	
430
+	{
405 431
 		uint32_t pos;
406 432
 		uint32_t lineadd;
407 433
 		uint32_t shape;
408 434
 
409
-		// Wait until DMA2D is ready
410
-		while(DMA2D->CR & DMA2D_CR_START);
411
-
412 435
 		#if GDISP_NEED_CONTROL
413 436
 			switch(g->g.Orientation) {
414 437
 			case GDISP_ROTATE_0:
@@ -438,13 +461,24 @@ LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay* g) {
438 461
 			lineadd = g->g.Width - g->p.cx;
439 462
 			shape = (g->p.cx << 16) | (g->p.cy);
440 463
 		#endif
441
-		
464
+
465
+		// Wait until DMA2D is ready
466
+		while(DMA2D->CR & DMA2D_CR_START);
467
+
442 468
 		// Start the DMA2D
443 469
 		DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, pos);
444 470
 		DMA2D->OOR = lineadd;
445 471
 		DMA2D->NLR = shape;
446
-		DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color));
447
-		DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START;	
472
+		#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
473
+			// As we don't support ARGB pixel types in uGFX yet we will
474
+			// use RGB with an inverted alpha value for compatibility
475
+			// ie. 0x00FFFFFF is fully opaque white, 0xFFFFFFFF is fully transparent white
476
+			DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color)) ^ 0xFF000000;
477
+		#else
478
+			DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color));
479
+		#endif
480
+		;
481
+		DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START;
448 482
 	}
449 483
 
450 484
 	/* Oops - the DMA2D only supports GDISP_ROTATE_0.
@@ -464,7 +498,7 @@ LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay* g) {
464 498
 	 * access to the framebuffer is fast - probably faster than DMA2D.
465 499
 	 * It just uses more CPU.
466 500
 	 */
467
-	#if GDISP_HARDWARE_BITFILLS 
501
+	#if GDISP_HARDWARE_BITFILLS
468 502
 		// Uses p.x,p.y  p.cx,p.cy  p.x1,p.y1 (=srcx,srcy)  p.x2 (=srccx), p.ptr (=buffer)
469 503
 		LLDSPEC void gdisp_lld_blit_area(GDisplay* g) {
470 504
 			// Wait until DMA2D is ready
@@ -473,7 +507,7 @@ LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay* g) {
473 507
 			// Source setup
474 508
 			DMA2D->FGMAR = LTDC_PIXELBYTES * (g->p.y1 * g->p.x2 + g->p.x1) + (uint32_t)g->p.ptr;
475 509
 			DMA2D->FGOR = g->p.x2 - g->p.cx;
476
-		
510
+
477 511
 			// Output setup
478 512
 			DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, PIXIL_POS(g, g->p.x, g->p.y));
479 513
 			DMA2D->OOR = g->g.Width - g->p.cx;

+ 15 - 5
drivers/gdisp/STM32LTDC/gdisp_lld_config.h

@@ -21,8 +21,15 @@
21 21
 
22 22
 // Both these pixel formats are supported - pick one.
23 23
 // RGB565 obviously is faster and uses less RAM but with lower color resolution than RGB888
24
-#define GDISP_LLD_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
25
-//#define GDISP_LLD_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
24
+
25
+#if defined(GDISP_LTDC_USE_RGB565) && GDISP_LTDC_USE_RGB565
26
+	#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
27
+	#if GDISP_TOTAL_DISPLAYS > 1
28
+		#error "LTDC: You must use RGB888 pixel format with LTDC when using dual layers as only RGB888 currently supports using alpha"
29
+	#endif
30
+#else
31
+	#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB888
32
+#endif
26 33
 
27 34
 
28 35
 /*===========================================================================*/
@@ -35,9 +42,12 @@
35 42
 
36 43
 	// Accelerated bitfills are also possible but only for GDISP_ROTATE_0
37 44
 	//	and if no color translation is required (for now)
38
-	#if !GDISP_NEED_CONTROL && GDISP_PIXELFORMAT == GDISP_LLD_PIXELFORMAT
39
- 		#define GDISP_HARDWARE_BITFILLS	TRUE
40
-	#endif
45
+	// Oops - this is not working and adds little performance benefit
46
+	//	so we will just disable it for the near future.
47
+//	#if !GDISP_NEED_CONTROL && !defined(GDISP_PIXELFORMAT)
48
+// 		#define GDISP_HARDWARE_BITFILLS	TRUE
49
+//	#endif
50
+
41 51
 #endif /* GDISP_USE_DMA2D */
42 52
 
43 53
 #endif	/* GFX_USE_GDISP */

+ 7 - 0
src/gdisp/gdisp_colors.h

@@ -328,6 +328,13 @@ typedef uint16_t	colorformat;
328 328
 	#endif
329 329
 	#define HTML2COLOR(h)		((COLOR_TYPE)(HTML2COLOR_R(h) | HTML2COLOR_G(h) | HTML2COLOR_B(h)))
330 330
 
331
+	// Special hack to allow alpha on RGB888
332
+	#if GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
333
+		#define GFXTRANSPARENT		(0xFF000000)
334
+		#define AHTML2COLOR(h)		((h) ^ 0xFF000000)
335
+ 		#define ARGB2COLOR(a,r,g,b)	((((COLOR_TYPE)(((a) ^ 0xFF) & 0xFF)) << 24) | RGB2COLOR_R(r) | RGB2COLOR_G(g) | RGB2COLOR_B(b))
336
+	#endif
337
+
331 338
 //-------------------------
332 339
 //	Gray-scale color system
333 340
 //-------------------------