2024-05-08 04:53 AM - edited 2024-05-17 09:38 PM
I am using a STM32F429BI module + 7" LCD RGB to display the amplifier settings and also a vu-meter.
https://it.aliexpress.com/item/1005002482177244.html
http://www.audiodesignguide.com/sw1/20240507_215200.mp4
I would like to increase the speed of refresh to eliminate the tear flicker of vu-meter using the Double buffering like described in this following doc (see Multiple buffering techniques such as the double buffering) or other methods, do you know how to modify my code ?
I am using this function to plot the pixel for vu-meter
void BSP_LCD_DrawPixel(uint16_t Xpos, uint16_t Ypos, uint32_t RGB_Code)
{
/* Write data value to all SDRAM memory */
if(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565)
{ /* RGB565 format */
*(__IO uint16_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (2*(Ypos*BSP_LCD_GetXSize() + Xpos))) = (uint16_t)RGB_Code;
}
else
{ /* ARGB8888 format */
*(__IO uint32_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (4*(Ypos*BSP_LCD_GetXSize() + Xpos))) = RGB_Code;
}
}
this function to read the background of vu-meter to restore the pixel before plot a new value
uint32_t BSP_LCD_ReadPixel(uint16_t Xpos, uint16_t Ypos)
{
uint32_t ret = 0;
if(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888)
{
/* Read data value from SDRAM memory */
// ret = *(__IO uint32_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (2*(Ypos*BSP_LCD_GetXSize() + Xpos)));
ret = *(__IO uint32_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (4*(Ypos*BSP_LCD_GetXSize() + Xpos)));
}
else if(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB888)
{
/* Read data value from SDRAM memory */
ret = (*(__IO uint32_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (2*(Ypos*BSP_LCD_GetXSize() + Xpos))) & 0x00FFFFFF);
}
else if((hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) || \
(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB4444) || \
(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_AL88))
{
/* Read data value from SDRAM memory */
ret = *(__IO uint16_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (2*(Ypos*BSP_LCD_GetXSize() + Xpos)));
}
else
{
/* Read data value from SDRAM memory */
ret = *(__IO uint8_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (2*(Ypos*BSP_LCD_GetXSize() + Xpos)));
}
return ret;
}
and this configuration set
void StartDefaultTask(void const * argument)
{
MX_GPIO_Init();
MX_CRC_Init();
MX_DMA2D_Init();
MX_FMC_Init();
MX_LTDC_Init();
MX_TIM4_Init();
.....
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/** Initializes the CPU, AHB and APB busses clocks
*/
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;
RCC_OscInitStruct.PLL.PLLM = 15;
RCC_OscInitStruct.PLL.PLLN = 144;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 5;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|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;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
PeriphClkInitStruct.PLLSAI.PLLSAIN = 60;
PeriphClkInitStruct.PLLSAI.PLLSAIR = 2;
PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}
static void MX_DMA2D_Init(void)
{
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_M2M;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
hdma2d.Init.OutputOffset = 0;
hdma2d.LayerCfg[1].InputOffset = 0;
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[1].InputAlpha = 0;
if (HAL_DMA2D_Init(&hdma2d) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN DMA2D_Init 2 */
/* USER CODE END DMA2D_Init 2 */
}
static void MX_LTDC_Init(void)
{
/* USER CODE BEGIN LTDC_Init 0 */
/* USER CODE END LTDC_Init 0 */
LTDC_LayerCfgTypeDef pLayerCfg = {0};
/* USER CODE BEGIN LTDC_Init 1 */
/* USER CODE END LTDC_Init 1 */
hltdc.Instance = LTDC;
hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
#define HBP 80
#define VBP 40
#define HSW 1
#define VSW 1
#define HFP 190
#define VFP 22
#define LCD_Width 800
#define LCD_Height 480
#define LCD_Pixels 800*480
#define LCD_MemoryAdd 0xD0000000
hltdc.Init.HorizontalSync = HSW - 1;
hltdc.Init.VerticalSync = VSW -1 ;
hltdc.Init.AccumulatedHBP = HBP + HSW -1;
hltdc.Init.AccumulatedVBP = VBP + VSW -1;
hltdc.Init.AccumulatedActiveW = LCD_Width + HSW + HBP -1;
hltdc.Init.AccumulatedActiveH = LCD_Height + VSW + VBP -1;
hltdc.Init.TotalWidth = LCD_Width + HSW + HBP + HFP - 1;
hltdc.Init.TotalHeigh = LCD_Height + VSW + VBP + VFP - 1;
hltdc.Init.Backcolor.Blue = 0;
hltdc.Init.Backcolor.Green = 0;
hltdc.Init.Backcolor.Red = 0;
if (HAL_LTDC_Init(&hltdc) != HAL_OK)
{
Error_Handler();
}
pLayerCfg.WindowX0 = 0;
pLayerCfg.WindowX1 = 799;
pLayerCfg.WindowY0 = 0;
pLayerCfg.WindowY1 = 479;
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;
pLayerCfg.Alpha = 255;
pLayerCfg.Alpha0 = 0;
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
pLayerCfg.FBStartAdress = 0xD0000000;
pLayerCfg.ImageWidth = 800;
pLayerCfg.ImageHeight = 480;
pLayerCfg.Backcolor.Blue = 0;
pLayerCfg.Backcolor.Green = 0;
pLayerCfg.Backcolor.Red = 0;
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN LTDC_Init 2 */
/* USER CODE END LTDC_Init 2 */
}
Yesterday evening I tried to use the following function with DMA to write the 3 x 190 pixels of vu-meter but the result is worst
void BSP_LCD_DrawHLine(uint16_t Xpos, uint16_t Ypos, uint16_t Length)
{
uint32_t Xaddress = 0;
/* Get the line address */
Xaddress = (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress) + 4*(BSP_LCD_GetXSize()*Ypos + Xpos);
/* Write line */
LL_FillBuffer(ActiveLayer, (uint32_t *)Xaddress, Length, 1, 0, DrawProp[ActiveLayer].TextColor);
}
2024-05-31 03:55 AM - edited 2024-05-31 03:55 AM
Hello @Ciuffoly www.audiodesignguide ,
Could you please refer to LSD datasheet and check if the LCD is adapted for the landscape mode or not?
Is your LCD support the horizontal refresh?
If the LCD isn't adapted for landscape mode, I recommend you to use command mode partial refresh, this will help to avoid tearing effect.
You can refer to example available in STM32CubeFW_F4 package available also on github.com: https://github.com/STMicroelectronics/STM32CubeF4/tree/master/Projects/STM32469I-Discovery/Examples/LCD_DSI/LCD_DSI_CmdMode_PartialRefresh
I hope this help you!
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-05-31 04:33 AM
Ok so a FANKE RGB070M1 800x480 V1.4 with AT070TN92 panel
https://www.beyondinfinite.com/lcd/Library/Innolux/AT070TN92.pdf
2024-05-31 09:11 AM
2024-05-31 10:23 AM
800x480 is resolution on edge F4 and your code require be optimal plus your hw as SDRAM used or next parts need be optimal. Your show code with ifs for many color modes is brutal unoptimal... Why you dont try use TouchGFX?