embox
362 строки · 11.4 Кб
1/**
2* @file
3*
4* @date Oct 18, 2021
5* @author Anton Bondarev
6*/
7
8#include <stdint.h>9
10#include "stm32cube_custom_lcd.h"11
12#include <framework/mod/options.h>13
14#define RK043FN48H_HSYNC ((uint16_t)OPTION_GET(NUMBER, vsync)) /* Horizontal synchronization */15#define RK043FN48H_HBP ((uint16_t)OPTION_GET(NUMBER, hbp)) /* Horizontal back porch */16#define RK043FN48H_HFP ((uint16_t)OPTION_GET(NUMBER, hfp)) /* Horizontal front porch */17#define RK043FN48H_VSYNC ((uint16_t)OPTION_GET(NUMBER, vsync)) /* Vertical synchronization */18#define RK043FN48H_VBP ((uint16_t)OPTION_GET(NUMBER, vbp)) /* Vertical back porch */19#define RK043FN48H_VFP ((uint16_t)OPTION_GET(NUMBER, vfp)) /* Vertical front porch */20
21#define RK043FN48H_FREQUENCY_DIVIDER 5 /* LCD Frequency divider */22
23LTDC_HandleTypeDef hLtdcHandler;24static DMA2D_HandleTypeDef hDma2dHandler;25
26/* Default LCD configuration with LCD Layer 1 */
27static uint32_t ActiveLayer = 0;28static LCD_DrawPropTypeDef DrawProp[MAX_LAYER_NUMBER];29
30/**
31* @brief Initializes the LTDC MSP.
32* @param hltdc: LTDC handle
33* @param Params
34* @retval None
35*/
36__weak void BSP_LCD_MspInit(LTDC_HandleTypeDef *hltdc, void *Params)37{
38GPIO_InitTypeDef gpio_init_structure;39
40/* Enable the LTDC and DMA2D clocks */41__HAL_RCC_LTDC_CLK_ENABLE();42__HAL_RCC_DMA2D_CLK_ENABLE();43
44/* Enable GPIOs clock */45__HAL_RCC_GPIOE_CLK_ENABLE();46__HAL_RCC_GPIOG_CLK_ENABLE();47__HAL_RCC_GPIOI_CLK_ENABLE();48__HAL_RCC_GPIOJ_CLK_ENABLE();49__HAL_RCC_GPIOK_CLK_ENABLE();50LCD_DISP_GPIO_CLK_ENABLE();51LCD_BL_CTRL_GPIO_CLK_ENABLE();52
53/*** LTDC Pins configuration ***/54/* GPIOE configuration */55gpio_init_structure.Pin = GPIO_PIN_4;56gpio_init_structure.Mode = GPIO_MODE_AF_PP;57gpio_init_structure.Pull = GPIO_NOPULL;58gpio_init_structure.Speed = GPIO_SPEED_FAST;59gpio_init_structure.Alternate = GPIO_AF14_LTDC;60HAL_GPIO_Init(GPIOE, &gpio_init_structure);61
62/* GPIOG configuration */63gpio_init_structure.Pin = GPIO_PIN_12;64gpio_init_structure.Mode = GPIO_MODE_AF_PP;65gpio_init_structure.Alternate = GPIO_AF9_LTDC;66HAL_GPIO_Init(GPIOG, &gpio_init_structure);67
68/* GPIOI LTDC alternate configuration */69gpio_init_structure.Pin = GPIO_PIN_9 | GPIO_PIN_10 | \70GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;71gpio_init_structure.Mode = GPIO_MODE_AF_PP;72gpio_init_structure.Alternate = GPIO_AF14_LTDC;73HAL_GPIO_Init(GPIOI, &gpio_init_structure);74
75/* GPIOJ configuration */76gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \77GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | \78GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | \79GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;80gpio_init_structure.Mode = GPIO_MODE_AF_PP;81gpio_init_structure.Alternate = GPIO_AF14_LTDC;82HAL_GPIO_Init(GPIOJ, &gpio_init_structure);83
84/* GPIOK configuration */85gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | \86GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;87gpio_init_structure.Mode = GPIO_MODE_AF_PP;88gpio_init_structure.Alternate = GPIO_AF14_LTDC;89HAL_GPIO_Init(GPIOK, &gpio_init_structure);90
91/* LCD_DISP GPIO configuration */92gpio_init_structure.Pin = LCD_DISP_PIN; /* LCD_DISP pin has to be manually controlled */93gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP;94HAL_GPIO_Init(LCD_DISP_GPIO_PORT, &gpio_init_structure);95
96/* LCD_BL_CTRL GPIO configuration */97gpio_init_structure.Pin = LCD_BL_CTRL_PIN; /* LCD_BL_CTRL pin has to be manually controlled */98gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP;99HAL_GPIO_Init(LCD_BL_CTRL_GPIO_PORT, &gpio_init_structure);100}
101
102/**
103* @brief Clock Config.
104* @param hltdc: LTDC handle
105* @param Params
106* @note This API is called by BSP_LCD_Init()
107* Being __weak it can be overwritten by the application
108* @retval None
109*/
110__weak void BSP_LCD_ClockConfig(LTDC_HandleTypeDef *hltdc, void *Params)111{
112static RCC_PeriphCLKInitTypeDef periph_clk_init_struct;113
114/* RK043FN48H LCD clock configuration */115/* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */116/* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */117/* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz */118/* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_4 = 38.4/4 = 9.6Mhz */119periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;120periph_clk_init_struct.PLLSAI.PLLSAIN = 192;121periph_clk_init_struct.PLLSAI.PLLSAIR = RK043FN48H_FREQUENCY_DIVIDER;122periph_clk_init_struct.PLLSAIDivR = RCC_PLLSAIDIVR_4;123HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct);124}
125
126/**
127* @brief Initializes the LCD.
128* @retval LCD state
129*/
130uint8_t bsp_lcd_init(uint16_t height, uint16_t width)131{
132/* Timing Configuration */133hLtdcHandler.Init.HorizontalSync = (RK043FN48H_HSYNC - 1);134hLtdcHandler.Init.VerticalSync = (RK043FN48H_VSYNC - 1);135hLtdcHandler.Init.AccumulatedHBP = (RK043FN48H_HSYNC + RK043FN48H_HBP - 1);136hLtdcHandler.Init.AccumulatedVBP = (RK043FN48H_VSYNC + RK043FN48H_VBP - 1);137hLtdcHandler.Init.AccumulatedActiveH = (height + RK043FN48H_VSYNC + RK043FN48H_VBP - 1);138hLtdcHandler.Init.AccumulatedActiveW = (width + RK043FN48H_HSYNC + RK043FN48H_HBP - 1);139hLtdcHandler.Init.TotalHeigh = (height + RK043FN48H_VSYNC + RK043FN48H_VBP + RK043FN48H_VFP - 1);140hLtdcHandler.Init.TotalWidth = (width + RK043FN48H_HSYNC + RK043FN48H_HBP + RK043FN48H_HFP - 1);141
142/* LCD clock configuration */143BSP_LCD_ClockConfig(&hLtdcHandler, NULL);144
145/* Initialize the LCD pixel width and pixel height */146hLtdcHandler.LayerCfg->ImageWidth = width;147hLtdcHandler.LayerCfg->ImageHeight = height;148
149/* Background value */150hLtdcHandler.Init.Backcolor.Blue = 0;151hLtdcHandler.Init.Backcolor.Green = 0;152hLtdcHandler.Init.Backcolor.Red = 0;153
154/* Polarity */155hLtdcHandler.Init.HSPolarity = LTDC_HSPOLARITY_AL;156hLtdcHandler.Init.VSPolarity = LTDC_VSPOLARITY_AL;157hLtdcHandler.Init.DEPolarity = LTDC_DEPOLARITY_AL;158hLtdcHandler.Init.PCPolarity = LTDC_PCPOLARITY_IPC;159hLtdcHandler.Instance = LTDC;160
161if(HAL_LTDC_GetState(&hLtdcHandler) == HAL_LTDC_STATE_RESET)162{163/* Initialize the LCD Msp: this __weak function can be rewritten by the application */164BSP_LCD_MspInit(&hLtdcHandler, NULL);165}166HAL_LTDC_Init(&hLtdcHandler);167
168/* Assert display enable LCD_DISP pin */169HAL_GPIO_WritePin(LCD_DISP_GPIO_PORT, LCD_DISP_PIN, GPIO_PIN_SET);170
171/* Assert backlight LCD_BL_CTRL pin */172HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_PORT, LCD_BL_CTRL_PIN, GPIO_PIN_SET);173
174#if !defined(DATA_IN_ExtSDRAM)175/* Initialize the SDRAM */176BSP_SDRAM_Init();177#endif178
179/* Initialize the font */180// BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
181
182return LCD_OK;183}
184
185
186/**
187* @brief Gets the LCD X size.
188* @retval Used LCD X size
189*/
190uint32_t bsp_lcd_getxsize(void)191{
192return hLtdcHandler.LayerCfg[ActiveLayer].ImageWidth;193}
194
195/**
196* @brief Gets the LCD Y size.
197* @retval Used LCD Y size
198*/
199uint32_t bsp_lcd_getysize(void)200{
201return hLtdcHandler.LayerCfg[ActiveLayer].ImageHeight;202}
203
204/**
205* @brief Set the LCD X size.
206* @param imageWidthPixels : image width in pixels unit
207* @retval None
208*/
209void bsp_lcd_setxsize(uint32_t imageWidthPixels)210{
211hLtdcHandler.LayerCfg[ActiveLayer].ImageWidth = imageWidthPixels;212}
213
214/**
215* @brief Set the LCD Y size.
216* @param imageHeightPixels : image height in lines unit
217* @retval None
218*/
219void bsp_lcd_setysize(uint32_t imageHeightPixels)220{
221hLtdcHandler.LayerCfg[ActiveLayer].ImageHeight = imageHeightPixels;222}
223
224/**
225* @brief Draws a pixel on LCD.
226* @param Xpos: X position
227* @param Ypos: Y position
228* @param RGB_Code: Pixel color in ARGB mode (8-8-8-8)
229* @retval None
230*/
231void bsp_lcd_drawpixel(uint16_t Xpos, uint16_t Ypos, uint32_t RGB_Code)232{
233/* Write data value to all SDRAM memory */234if(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565)235{ /* RGB565 format */236*(__IO uint16_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (2*(Ypos*bsp_lcd_getxsize() + Xpos))) = (uint16_t)RGB_Code;237}238else239{ /* ARGB8888 format */240*(__IO uint32_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (4*(Ypos*bsp_lcd_getxsize() + Xpos))) = RGB_Code;241}242}
243
244
245/**
246* @brief Sets the LCD text color.
247* @param Color: Text color code ARGB(8-8-8-8)
248* @retval None
249*/
250void bsp_lcd_settextcolor(uint32_t Color)251{
252DrawProp[ActiveLayer].TextColor = Color;253}
254
255/**
256* @brief Gets the LCD text color.
257* @retval Used text color.
258*/
259uint32_t bsp_lcd_gettextcolor(void)260{
261return DrawProp[ActiveLayer].TextColor;262}
263
264/**
265* @brief Sets the LCD background color.
266* @param Color: Layer background color code ARGB(8-8-8-8)
267* @retval None
268*/
269void bsp_lcd_setbackcolor(uint32_t Color)270{
271DrawProp[ActiveLayer].BackColor = Color;272}
273
274/**
275* @brief Gets the LCD background color.
276* @retval Used background colour
277*/
278uint32_t BSP_LCD_GetBackColor(void)279{
280return DrawProp[ActiveLayer].BackColor;281}
282
283/**
284* @brief Selects the LCD Layer.
285* @param LayerIndex: Layer foreground or background
286* @retval None
287*/
288void bsp_lcd_selectlayer(uint32_t LayerIndex)289{
290ActiveLayer = LayerIndex;291}
292
293
294static void LL_FillBuffer(uint32_t LayerIndex, void *pDst, uint32_t xSize, uint32_t ySize, uint32_t OffLine, uint32_t ColorIndex)295{
296/* Register to memory mode with ARGB8888 as color Mode */297hDma2dHandler.Init.Mode = DMA2D_R2M;298if(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565)299{ /* RGB565 format */300hDma2dHandler.Init.ColorMode = DMA2D_RGB565;301}302else303{ /* ARGB8888 format */304hDma2dHandler.Init.ColorMode = DMA2D_ARGB8888;305}306hDma2dHandler.Init.OutputOffset = OffLine;307
308hDma2dHandler.Instance = DMA2D;309
310/* DMA2D Initialization */311if(HAL_DMA2D_Init(&hDma2dHandler) == HAL_OK)312{313if(HAL_DMA2D_ConfigLayer(&hDma2dHandler, LayerIndex) == HAL_OK)314{315if (HAL_DMA2D_Start(&hDma2dHandler, ColorIndex, (uint32_t)pDst, xSize, ySize) == HAL_OK)316{317/* Polling For DMA transfer */318HAL_DMA2D_PollForTransfer(&hDma2dHandler, 10);319}320}321}322}
323
324/**
325* @brief Clears the hole LCD.
326* @param Color: Color of the background
327* @retval None
328*/
329void bsp_lcd_clear(uint32_t Color)330{
331/* Clear the LCD */332LL_FillBuffer(ActiveLayer, (uint32_t *)(hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress), bsp_lcd_getxsize(), bsp_lcd_getysize(), 0, Color);333}
334
335
336/**
337* @brief Draws a full rectangle.
338* @param Xpos: X position
339* @param Ypos: Y position
340* @param Width: Rectangle width
341* @param Height: Rectangle height
342* @retval None
343*/
344void bsp_lcd_fillrect(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)345{
346uint32_t x_address = 0;347
348/* Set the text color */349bsp_lcd_settextcolor(DrawProp[ActiveLayer].TextColor);350
351/* Get the rectangle start address */352if(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565)353{ /* RGB565 format */354x_address = (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress) + 2*(bsp_lcd_getxsize()*Ypos + Xpos);355}356else357{ /* ARGB8888 format */358x_address = (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress) + 4*(bsp_lcd_getxsize()*Ypos + Xpos);359}360/* Fill the rectangle */361LL_FillBuffer(ActiveLayer, (uint32_t *)x_address, Width, Height, (bsp_lcd_getxsize() - Width), DrawProp[ActiveLayer].TextColor);362}
363
364
365