
Code commenté du projet LED
Dependencies: BSP_DISCO_F746NG
Diff: hal_stm_lvgl/tft/tft.c
- Revision:
- 5:071136c3eefa
- Parent:
- 3:4f5dc253eb7b
--- a/hal_stm_lvgl/tft/tft.c Sun Apr 25 12:35:07 2021 +0000 +++ b/hal_stm_lvgl/tft/tft.c Tue Jun 15 19:35:57 2021 +0000 @@ -2,7 +2,7 @@ * @file tft.c * */ - + /********************* * INCLUDES *********************/ @@ -10,29 +10,31 @@ #include "lvgl/lvgl.h" #include <string.h> #include <stdlib.h> - + #include "tft.h" #include "stm32f7xx.h" #include "stm32746g_discovery.h" #include "stm32746g_discovery_sdram.h" #include "stm32746g_discovery_ts.h" #include "../Components/rk043fn48h/rk043fn48h.h" - + /********************* * DEFINES *********************/ - + #if LV_COLOR_DEPTH != 16 && LV_COLOR_DEPTH != 24 && LV_COLOR_DEPTH != 32 #error LV_COLOR_DEPTH must be 16, 24, or 32 #endif +#define LV_USE_GPU 0 + /** * @brief LCD status structure definition */ #define LCD_OK ((uint8_t)0x00) #define LCD_ERROR ((uint8_t)0x01) #define LCD_TIMEOUT ((uint8_t)0x02) - + /** * @brief LCD special pins */ @@ -41,45 +43,45 @@ #define LCD_DISP_GPIO_PORT GPIOI #define LCD_DISP_GPIO_CLK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() #define LCD_DISP_GPIO_CLK_DISABLE() __HAL_RCC_GPIOI_CLK_DISABLE() - + /* Backlight control pin */ #define LCD_BL_CTRL_PIN GPIO_PIN_3 #define LCD_BL_CTRL_GPIO_PORT GPIOK #define LCD_BL_CTRL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOK_CLK_ENABLE() #define LCD_BL_CTRL_GPIO_CLK_DISABLE() __HAL_RCC_GPIOK_CLK_DISABLE() - + #define CPY_BUF_DMA_STREAM DMA2_Stream0 #define CPY_BUF_DMA_CHANNEL DMA_CHANNEL_0 #define CPY_BUF_DMA_STREAM_IRQ DMA2_Stream0_IRQn #define CPY_BUF_DMA_STREAM_IRQHANDLER DMA2_Stream0_IRQHandler - + /********************** * TYPEDEFS **********************/ - + /********************** * STATIC PROTOTYPES **********************/ - + /*These 3 functions are needed by LittlevGL*/ static void ex_disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t * color_p); #if LV_USE_GPU static void gpu_mem_blend(lv_disp_drv_t *disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa); static void gpu_mem_fill(lv_disp_drv_t *disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width, const lv_area_t * fill_area, lv_color_t color); #endif - + static uint8_t LCD_Init(void); static void LCD_LayerRgb565Init(uint32_t FB_Address); static void LCD_DisplayOn(void); - + static void DMA_Config(void); static void DMA_TransferComplete(DMA_HandleTypeDef *han); static void DMA_TransferError(DMA_HandleTypeDef *han); - + #if LV_USE_GPU static void DMA2D_Config(void); #endif - + /********************** * STATIC VARIABLES **********************/ @@ -87,19 +89,19 @@ static DMA2D_HandleTypeDef Dma2dHandle; #endif static LTDC_HandleTypeDef hLtdcHandler; - + #if LV_COLOR_DEPTH == 16 typedef uint16_t uintpixel_t; #elif LV_COLOR_DEPTH == 24 || LV_COLOR_DEPTH == 32 typedef uint32_t uintpixel_t; #endif - + /* You can try to change buffer to internal ram by uncommenting line below and commenting * SDRAM one. */ //static uintpixel_t my_fb[TFT_HOR_RES * TFT_VER_RES]; - + static __IO uintpixel_t * my_fb = (__IO uintpixel_t*) (SDRAM_DEVICE_ADDR); - + static DMA_HandleTypeDef DmaHandle; static int32_t x1_flush; static int32_t y1_flush; @@ -107,107 +109,108 @@ static int32_t y2_fill; static int32_t y_fill_act; static const lv_color_t * buf_to_flush; - +static lv_disp_drv_t disp_drv; + static lv_disp_t *our_disp = NULL; /********************** * MACROS **********************/ - + /** * Initialize your display here */ - + void tft_init(void) { - /* There is only one display on STM32 */ - if(our_disp != NULL) - abort(); + /* There is only one display on STM32 */ + if(our_disp != NULL) + abort(); /* LCD Initialization */ LCD_Init(); - + /* LCD Initialization */ LCD_LayerRgb565Init((uint32_t)my_fb); - + /* Enable the LCD */ LCD_DisplayOn(); - + DMA_Config(); - + #if LV_USE_GPU != 0 DMA2D_Config(); #endif /*----------------------------- - * Create a buffer for drawing - *----------------------------*/ - + * Create a buffer for drawing + *----------------------------*/ + /* LittlevGL requires a buffer where it draws the objects. The buffer's has to be greater than 1 display row*/ - - static lv_disp_buf_t disp_buf_1; - static lv_color_t buf1_1[LV_HOR_RES_MAX * 68]; - static lv_color_t buf1_2[LV_HOR_RES_MAX * 68]; - lv_disp_buf_init(&disp_buf_1, buf1_1, buf1_2, LV_HOR_RES_MAX * 68); /*Initialize the display buffer*/ - - - /*----------------------------------- - * Register the display in LittlevGL - *----------------------------------*/ - - lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ - lv_disp_drv_init(&disp_drv); /*Basic initialization*/ - - /*Set up the functions to access to your display*/ - - /*Set the resolution of the display*/ - disp_drv.hor_res = 480; - disp_drv.ver_res = 272; - - /*Used to copy the buffer's content to the display*/ - disp_drv.flush_cb = ex_disp_flush; - - /*Set a display buffer*/ - disp_drv.buffer = &disp_buf_1; - - - /*Finally register the driver*/ - our_disp = lv_disp_drv_register(&disp_drv); + + static lv_disp_draw_buf_t buf; + static lv_color_t buf1_1[TFT_HOR_RES * 68]; + static lv_color_t buf1_2[TFT_HOR_RES * 68]; + lv_disp_draw_buf_init(&buf, buf1_1, buf1_2, TFT_HOR_RES * 68); /*Initialize the display buffer*/ + + + /*----------------------------------- + * Register the display in LittlevGL + *----------------------------------*/ + + /*Descriptor of a display driver*/ + lv_disp_drv_init(&disp_drv); /*Basic initialization*/ + + /*Set up the functions to access to your display*/ + + /*Set the resolution of the display*/ + disp_drv.hor_res = TFT_HOR_RES; + disp_drv.ver_res = TFT_VER_RES; + + /*Used to copy the buffer's content to the display*/ + disp_drv.flush_cb = ex_disp_flush; + + /*Set a display buffer*/ + disp_drv.draw_buf = &buf; + + + /*Finally register the driver*/ + our_disp = lv_disp_drv_register(&disp_drv); } - + /********************** * STATIC FUNCTIONS **********************/ - + /* Flush the content of the internal buffer the specific area on the display * You can use DMA or any hardware acceleration to do this operation in the background but * 'lv_flush_ready()' has to be called when finished * This function is required only when LV_VDB_SIZE != 0 in lv_conf.h*/ static void ex_disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t * color_p) { - int32_t x1 = area->x1; - int32_t x2 = area->x2; - int32_t y1 = area->y1; - int32_t y2 = area->y2; + int32_t x1 = area->x1; + int32_t x2 = area->x2; + int32_t y1 = area->y1; + int32_t y2 = area->y2; /*Return if the area is out the screen*/ - + if(x2 < 0) return; if(y2 < 0) return; if(x1 > TFT_HOR_RES - 1) return; if(y1 > TFT_VER_RES - 1) return; - + /*Truncate the area to the screen*/ int32_t act_x1 = x1 < 0 ? 0 : x1; int32_t act_y1 = y1 < 0 ? 0 : y1; int32_t act_x2 = x2 > TFT_HOR_RES - 1 ? TFT_HOR_RES - 1 : x2; int32_t act_y2 = y2 > TFT_VER_RES - 1 ? TFT_VER_RES - 1 : y2; - + x1_flush = act_x1; y1_flush = act_y1; x2_flush = act_x2; y2_fill = act_y2; y_fill_act = act_y1; buf_to_flush = color_p; - - SCB_CleanInvalidateDCache(); - SCB_InvalidateICache(); + + SCB_CleanInvalidateDCache(); + SCB_InvalidateICache(); /*##-7- Start the DMA transfer using the interrupt mode #*/ /* Configure the source, destination and buffer size DMA fields and Start DMA Stream transfer */ /* Enable All the DMA interrupts */ @@ -220,18 +223,18 @@ length); if(err != HAL_OK) { - while(1); /*Halt on error*/ + while(1); /*Halt on error*/ } } - - + + /** * @brief Configure LCD pins, and peripheral clocks. */ static void LCD_MspInit(void) { GPIO_InitTypeDef gpio_init_structure; - + /* Enable the LTDC and DMA2D clocks */ __HAL_RCC_LTDC_CLK_ENABLE(); #if LV_USE_GPU != 0 @@ -245,7 +248,7 @@ __HAL_RCC_GPIOK_CLK_ENABLE(); LCD_DISP_GPIO_CLK_ENABLE(); LCD_BL_CTRL_GPIO_CLK_ENABLE(); - + /*** LTDC Pins configuration ***/ /* GPIOE configuration */ gpio_init_structure.Pin = GPIO_PIN_4; @@ -254,20 +257,20 @@ gpio_init_structure.Speed = GPIO_SPEED_FAST; gpio_init_structure.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOE, &gpio_init_structure); - + /* GPIOG configuration */ gpio_init_structure.Pin = GPIO_PIN_12; gpio_init_structure.Mode = GPIO_MODE_AF_PP; gpio_init_structure.Alternate = GPIO_AF9_LTDC; HAL_GPIO_Init(GPIOG, &gpio_init_structure); - + /* GPIOI LTDC alternate configuration */ gpio_init_structure.Pin = GPIO_PIN_9 | GPIO_PIN_10 | \ GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; gpio_init_structure.Mode = GPIO_MODE_AF_PP; gpio_init_structure.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOI, &gpio_init_structure); - + /* GPIOJ configuration */ gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \ GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | \ @@ -276,32 +279,32 @@ gpio_init_structure.Mode = GPIO_MODE_AF_PP; gpio_init_structure.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOJ, &gpio_init_structure); - + /* GPIOK configuration */ gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | \ GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; gpio_init_structure.Mode = GPIO_MODE_AF_PP; gpio_init_structure.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOK, &gpio_init_structure); - + /* LCD_DISP GPIO configuration */ gpio_init_structure.Pin = LCD_DISP_PIN; /* LCD_DISP pin has to be manually controlled */ gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(LCD_DISP_GPIO_PORT, &gpio_init_structure); - + /* LCD_BL_CTRL GPIO configuration */ gpio_init_structure.Pin = LCD_BL_CTRL_PIN; /* LCD_BL_CTRL pin has to be manually controlled */ gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(LCD_BL_CTRL_GPIO_PORT, &gpio_init_structure); } - + /** * @brief Configure LTDC PLL. */ static void LCD_ClockConfig(void) { static RCC_PeriphCLKInitTypeDef periph_clk_init_struct; - + /* RK043FN48H LCD clock configuration */ /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */ @@ -313,7 +316,7 @@ periph_clk_init_struct.PLLSAIDivR = RCC_PLLSAIDIVR_4; HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct); } - + /** * @brief Initializes the LCD. * @retval LCD state @@ -321,7 +324,7 @@ static uint8_t LCD_Init(void) { /* Select the used LCD */ - + /* The RK043FN48H LCD 480x272 is selected */ /* Timing Configuration */ hLtdcHandler.Init.HorizontalSync = (RK043FN48H_HSYNC - 1); @@ -332,60 +335,60 @@ hLtdcHandler.Init.AccumulatedActiveW = (RK043FN48H_WIDTH + RK043FN48H_HSYNC + RK043FN48H_HBP - 1); hLtdcHandler.Init.TotalHeigh = (RK043FN48H_HEIGHT + RK043FN48H_VSYNC + RK043FN48H_VBP + RK043FN48H_VFP - 1); hLtdcHandler.Init.TotalWidth = (RK043FN48H_WIDTH + RK043FN48H_HSYNC + RK043FN48H_HBP + RK043FN48H_HFP - 1); - + /* LCD clock configuration */ LCD_ClockConfig(); - + /* Initialize the LCD pixel width and pixel height */ hLtdcHandler.LayerCfg->ImageWidth = RK043FN48H_WIDTH; hLtdcHandler.LayerCfg->ImageHeight = RK043FN48H_HEIGHT; - + /* Background value */ hLtdcHandler.Init.Backcolor.Blue = 0; hLtdcHandler.Init.Backcolor.Green = 0; hLtdcHandler.Init.Backcolor.Red = 0; - + /* Polarity */ hLtdcHandler.Init.HSPolarity = LTDC_HSPOLARITY_AL; hLtdcHandler.Init.VSPolarity = LTDC_VSPOLARITY_AL; hLtdcHandler.Init.DEPolarity = LTDC_DEPOLARITY_AL; hLtdcHandler.Init.PCPolarity = LTDC_PCPOLARITY_IPC; hLtdcHandler.Instance = LTDC; - + if(HAL_LTDC_GetState(&hLtdcHandler) == HAL_LTDC_STATE_RESET) { /* Initialize the LCD Msp: this __weak function can be rewritten by the application */ LCD_MspInit(); } HAL_LTDC_Init(&hLtdcHandler); - + /* Assert display enable LCD_DISP pin */ HAL_GPIO_WritePin(LCD_DISP_GPIO_PORT, LCD_DISP_PIN, GPIO_PIN_SET); - + /* Assert backlight LCD_BL_CTRL pin */ HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_PORT, LCD_BL_CTRL_PIN, GPIO_PIN_SET); - + BSP_SDRAM_Init(); - + uint32_t i; for(i = 0; i < (TFT_HOR_RES * TFT_VER_RES) ; i++) { my_fb[i] = 0; } - + return LCD_OK; } - + static void LCD_LayerRgb565Init(uint32_t FB_Address) { LTDC_LayerCfgTypeDef layer_cfg; - + /* Layer Init */ layer_cfg.WindowX0 = 0; layer_cfg.WindowX1 = TFT_HOR_RES; layer_cfg.WindowY0 = 0; layer_cfg.WindowY1 = TFT_VER_RES; - + #if LV_COLOR_DEPTH == 16 layer_cfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565; #elif LV_COLOR_DEPTH == 24 || LV_COLOR_DEPTH == 32 @@ -403,10 +406,10 @@ layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA; layer_cfg.ImageWidth = TFT_HOR_RES; layer_cfg.ImageHeight = TFT_VER_RES; - + HAL_LTDC_ConfigLayer(&hLtdcHandler, &layer_cfg, 0); } - + static void LCD_DisplayOn(void) { /* Display On */ @@ -414,12 +417,12 @@ HAL_GPIO_WritePin(LCD_DISP_GPIO_PORT, LCD_DISP_PIN, GPIO_PIN_SET); /* Assert LCD_DISP pin */ HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_PORT, LCD_BL_CTRL_PIN, GPIO_PIN_SET); /* Assert LCD_BL_CTRL pin */ } - + static void DMA_Config(void) { /*## -1- Enable DMA2 clock #################################################*/ __HAL_RCC_DMA2_CLK_ENABLE(); - + /*##-2- Select the DMA functional Parameters ###############################*/ DmaHandle.Init.Channel = CPY_BUF_DMA_CHANNEL; /* DMA_CHANNEL_0 */ DmaHandle.Init.Direction = DMA_MEMORY_TO_MEMORY; /* M2M transfer mode */ @@ -433,10 +436,10 @@ DmaHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; /* FIFO threshold: 1/4 full */ DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE; /* Memory burst */ DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; /* Peripheral burst */ - + /*##-3- Select the DMA instance to be used for the transfer : DMA2_Stream0 #*/ DmaHandle.Instance = CPY_BUF_DMA_STREAM; - + /*##-4- Initialize the DMA stream ##########################################*/ if(HAL_DMA_Init(&DmaHandle) != HAL_OK) { @@ -444,16 +447,16 @@ { } } - + /*##-5- Select Callbacks functions called after Transfer complete and Transfer error */ HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_CPLT_CB_ID, DMA_TransferComplete); HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_ERROR_CB_ID, DMA_TransferError); - + /*##-6- Configure NVIC for DMA transfer complete/error interrupts ##########*/ HAL_NVIC_SetPriority(CPY_BUF_DMA_STREAM_IRQ, 0, 0); HAL_NVIC_EnableIRQ(CPY_BUF_DMA_STREAM_IRQ); } - + /** * @brief DMA conversion complete callback * @note This function is executed when the transfer complete interrupt @@ -463,13 +466,13 @@ static void DMA_TransferComplete(DMA_HandleTypeDef *han) { y_fill_act ++; - + if(y_fill_act > y2_fill) { - SCB_CleanInvalidateDCache(); - SCB_InvalidateICache(); - lv_disp_flush_ready(&our_disp->driver); + SCB_CleanInvalidateDCache(); + SCB_InvalidateICache(); + lv_disp_flush_ready(&disp_drv); } else { - uint32_t length = (x2_flush - x1_flush + 1); + uint32_t length = (x2_flush - x1_flush + 1); buf_to_flush += x2_flush - x1_flush + 1; /*##-7- Start the DMA transfer using the interrupt mode ####################*/ /* Configure the source, destination and buffer size DMA fields and Start DMA Stream transfer */ @@ -480,11 +483,11 @@ if(HAL_DMA_Start_IT(han,(uint32_t)buf_to_flush, (uint32_t)&my_fb[y_fill_act * TFT_HOR_RES + x1_flush], length) != HAL_OK) { - while(1); /*Halt on error*/ + while(1); /*Halt on error*/ } } } - + /** * @brief DMA conversion error callback * @note This function is executed when the transfer error interrupt @@ -493,9 +496,9 @@ */ static void DMA_TransferError(DMA_HandleTypeDef *han) { - + } - + /** * @brief This function handles DMA Stream interrupt request. * @param None @@ -506,10 +509,10 @@ /* Check the interrupt and clear flag */ HAL_DMA_IRQHandler(&DmaHandle); } - - + + #if LV_USE_GPU != 0 - + static void Error_Handler(void) { while(1) @@ -525,9 +528,9 @@ */ static void DMA2D_TransferComplete(DMA2D_HandleTypeDef *hdma2d) { - + } - + /** * @brief DMA2D error callbacks * @param hdma2d: DMA2D handle @@ -537,9 +540,9 @@ */ static void DMA2D_TransferError(DMA2D_HandleTypeDef *hdma2d) { - + } - + /** * @brief DMA2D configuration. * @note This function Configure the DMA2D peripheral : @@ -564,11 +567,11 @@ Dma2dHandle.Init.ColorMode = DMA2D_ARGB8888; #endif Dma2dHandle.Init.OutputOffset = 0x0; - + /* DMA2D Callbacks Configuration */ Dma2dHandle.XferCpltCallback = DMA2D_TransferComplete; Dma2dHandle.XferErrorCallback = DMA2D_TransferError; - + /* Foreground Configuration */ Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA; Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF; @@ -577,9 +580,9 @@ #elif LV_COLOR_DEPTH == 24 || LV_COLOR_DEPTH == 32 Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888; #endif - + Dma2dHandle.LayerCfg[1].InputOffset = 0x0; - + /* Background Configuration */ Dma2dHandle.LayerCfg[0].AlphaMode = DMA2D_REPLACE_ALPHA; Dma2dHandle.LayerCfg[0].InputAlpha = 0xFF; @@ -589,18 +592,17 @@ Dma2dHandle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888; #endif Dma2dHandle.LayerCfg[0].InputOffset = 0x0; - + Dma2dHandle.Instance = DMA2D; - + /* DMA2D Initialization */ if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK) { /* Initialization Error */ Error_Handler(); } - + HAL_DMA2D_ConfigLayer(&Dma2dHandle, 0); HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1); } -#endif - +#endif \ No newline at end of file