You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
6.5 KiB
223 lines
6.5 KiB
2 years ago
|
#include "my_lcd.h"
|
||
|
|
||
|
#include "stm32469i_discovery_lcd.h"
|
||
|
#include "stm32469i_discovery_sdram.h"
|
||
|
|
||
|
#include "image_320x240_argb8888.h"
|
||
|
#include "life_augmented_argb8888.h"
|
||
|
|
||
|
extern LTDC_HandleTypeDef hltdc_eval;
|
||
|
extern DMA2D_HandleTypeDef hdma2d_eval;
|
||
|
|
||
|
#define LAYER0_ADDRESS (LCD_FB_START_ADDRESS)
|
||
|
|
||
|
static int32_t front_buffer = 0;
|
||
|
static int32_t pend_buffer = -1;
|
||
|
static uint32_t ImageIndex = 0;
|
||
|
|
||
|
static const uint32_t * Images[] =
|
||
|
{
|
||
|
image_320x240_argb8888,
|
||
|
life_augmented_argb8888,
|
||
|
};
|
||
|
|
||
|
static const uint32_t Buffers[] =
|
||
|
{
|
||
|
LAYER0_ADDRESS,
|
||
|
LAYER0_ADDRESS + (800*480*4),
|
||
|
};
|
||
|
|
||
|
static void OnError_Handler(uint32_t condition);
|
||
|
static void LCD_BriefDisplay(void);
|
||
|
static void CopyBuffer(uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize);
|
||
|
|
||
|
void MY_LCD_Init() {
|
||
|
uint8_t lcd_status = LCD_OK;
|
||
|
|
||
|
lcd_status = BSP_LCD_Init();
|
||
|
OnError_Handler(lcd_status != LCD_OK);
|
||
|
|
||
|
BSP_LCD_LayerDefaultInit(0, LAYER0_ADDRESS);
|
||
|
BSP_LCD_SelectLayer(0);
|
||
|
|
||
|
/* Set LTDC Line Event */
|
||
|
HAL_LTDC_ProgramLineEvent(&hltdc_eval, 0);
|
||
|
|
||
|
/* Display example brief */
|
||
|
LCD_BriefDisplay();
|
||
|
|
||
|
/* Copy Buffer 0 into buffer 1, so only image area to be redrawn later */
|
||
|
CopyBuffer((uint32_t *)Buffers[0], (uint32_t *)Buffers[1], 0, 0, 800, 480);
|
||
|
}
|
||
|
|
||
|
void MY_LCD_Tick() {
|
||
|
if(pend_buffer < 0)
|
||
|
{
|
||
|
/* Prepare back buffer */
|
||
|
CopyBuffer((uint32_t *)Images[ImageIndex++], (uint32_t *)Buffers[1- front_buffer], 240, 160, 320, 240);
|
||
|
pend_buffer = 1- front_buffer;
|
||
|
|
||
|
if(ImageIndex >= 2)
|
||
|
{
|
||
|
ImageIndex = 0;
|
||
|
}
|
||
|
|
||
|
/* Wait some time before switching to next stage */
|
||
|
HAL_Delay(2000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void My_SystemClock_Config(void)
|
||
|
{
|
||
|
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
||
|
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||
|
HAL_StatusTypeDef ret = HAL_OK;
|
||
|
|
||
|
/* Enable Power Control clock */
|
||
|
__HAL_RCC_PWR_CLK_ENABLE();
|
||
|
|
||
|
/* The voltage scaling allows optimizing the power consumption when the device is
|
||
|
clocked below the maximum system frequency, to update the voltage scaling value
|
||
|
regarding system frequency refer to product datasheet. */
|
||
|
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||
|
|
||
|
/* Enable HSE Oscillator and activate PLL with HSE as source */
|
||
|
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||
|
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||
|
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||
|
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||
|
#if defined(USE_STM32469I_DISCO_REVA)
|
||
|
RCC_OscInitStruct.PLL.PLLM = 25;
|
||
|
#else
|
||
|
RCC_OscInitStruct.PLL.PLLM = 8;
|
||
|
#endif /* USE_STM32469I_DISCO_REVA */
|
||
|
RCC_OscInitStruct.PLL.PLLN = 360;
|
||
|
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||
|
RCC_OscInitStruct.PLL.PLLQ = 7;
|
||
|
RCC_OscInitStruct.PLL.PLLR = 6;
|
||
|
|
||
|
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||
|
if(ret != HAL_OK)
|
||
|
{
|
||
|
while(1) { ; }
|
||
|
}
|
||
|
|
||
|
/* Activate the OverDrive to reach the 180 MHz Frequency */
|
||
|
ret = HAL_PWREx_EnableOverDrive();
|
||
|
if(ret != HAL_OK)
|
||
|
{
|
||
|
while(1) { ; }
|
||
|
}
|
||
|
|
||
|
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
|
||
|
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
|
||
|
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||
|
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||
|
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||
|
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||
|
|
||
|
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
|
||
|
if(ret != HAL_OK)
|
||
|
{
|
||
|
while(1) { ; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief On Error Handler on condition TRUE.
|
||
|
* @param condition : Can be TRUE or FALSE
|
||
|
* @retval None
|
||
|
*/
|
||
|
static void OnError_Handler(uint32_t condition)
|
||
|
{
|
||
|
if(condition)
|
||
|
{
|
||
|
BSP_LED_On(LED3);
|
||
|
while(1) { ; } /* Blocking on error */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Line Event callback.
|
||
|
* @param hltdc: pointer to a LTDC_HandleTypeDef structure that contains
|
||
|
* the configuration information for the LTDC.
|
||
|
* @retval None
|
||
|
*/
|
||
|
void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc)
|
||
|
{
|
||
|
if(pend_buffer >= 0)
|
||
|
{
|
||
|
LTDC_LAYER(hltdc, 0)->CFBAR = ((uint32_t)Buffers[pend_buffer]);
|
||
|
__HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(hltdc);
|
||
|
|
||
|
front_buffer = pend_buffer;
|
||
|
pend_buffer = -1;
|
||
|
}
|
||
|
|
||
|
HAL_LTDC_ProgramLineEvent(hltdc, 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Display Example description.
|
||
|
* @param None
|
||
|
* @retval None
|
||
|
*/
|
||
|
static void LCD_BriefDisplay(void)
|
||
|
{
|
||
|
BSP_LCD_Clear(LCD_COLOR_WHITE);
|
||
|
BSP_LCD_SetBackColor(LCD_COLOR_BLUE);
|
||
|
BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
|
||
|
BSP_LCD_FillRect(0, 0, 800, 112);
|
||
|
BSP_LCD_SetTextColor(LCD_COLOR_WHITE);
|
||
|
BSP_LCD_DisplayStringAtLine(1, (uint8_t *)" LCD_DSI_VideoMode_DoubleBuffering");
|
||
|
BSP_LCD_SetFont(&Font16);
|
||
|
BSP_LCD_DisplayStringAtLine(4, (uint8_t *)"This example shows how to display images on LCD DSI using two buffers");
|
||
|
BSP_LCD_DisplayStringAtLine(5, (uint8_t *)"one for display and the other for draw ");
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Converts a line to an ARGB8888 pixel format.
|
||
|
* @param pSrc: Pointer to source buffer
|
||
|
* @param pDst: Output color
|
||
|
* @param xSize: Buffer width
|
||
|
* @param ColorMode: Input color mode
|
||
|
* @retval None
|
||
|
*/
|
||
|
static void CopyBuffer(uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize)
|
||
|
{
|
||
|
|
||
|
uint32_t destination = (uint32_t)pDst + (y * 800 + x) * 4;
|
||
|
uint32_t source = (uint32_t)pSrc;
|
||
|
|
||
|
/*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/
|
||
|
hdma2d_eval.Init.Mode = DMA2D_M2M;
|
||
|
hdma2d_eval.Init.ColorMode = DMA2D_ARGB8888;
|
||
|
hdma2d_eval.Init.OutputOffset = 800 - xsize;
|
||
|
|
||
|
/*##-2- DMA2D Callbacks Configuration ######################################*/
|
||
|
hdma2d_eval.XferCpltCallback = NULL;
|
||
|
|
||
|
/*##-3- Foreground Configuration ###########################################*/
|
||
|
hdma2d_eval.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
||
|
hdma2d_eval.LayerCfg[1].InputAlpha = 0xFF;
|
||
|
hdma2d_eval.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
|
||
|
hdma2d_eval.LayerCfg[1].InputOffset = 0;
|
||
|
|
||
|
hdma2d_eval.Instance = DMA2D;
|
||
|
|
||
|
/* DMA2D Initialization */
|
||
|
if(HAL_DMA2D_Init(&hdma2d_eval) == HAL_OK)
|
||
|
{
|
||
|
if(HAL_DMA2D_ConfigLayer(&hdma2d_eval, 1) == HAL_OK)
|
||
|
{
|
||
|
if (HAL_DMA2D_Start(&hdma2d_eval, source, destination, xsize, ysize) == HAL_OK)
|
||
|
{
|
||
|
/* Polling For DMA transfer */
|
||
|
HAL_DMA2D_PollForTransfer(&hdma2d_eval, 100);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|