2022-02-22 04:38 AM
Hello,
I hope someone can help me. After days over days reading docs, other questions and so on i am still confused how all the LTDC and DSI stuff works.
OK, so what i have is a STM32F469 Disovery board which already has a display on it.
I create a project in touchgfx with just a blue screen and 4 white boxes in the corners.
Opened in the IDE i can upload it and it works. No wonder, it is all original.
Now i changed the display using the same FPC connector. I am using a small pcb for changing the wires to match the spec of the new display.
It is also 2 lane DSI.
As program "template" i still use one of the 469-disco
I removed all the otm8009a stuff, and used the power-on sequence of the new display with the HX8363 instead of the OTM8009a
HAL_DSI_ShortWrite(&hdsi, 0x00, DSI_DCS_SHORT_PKT_WRITE_P1, 0x11, 0x00);
HAL_Delay(201);
uint8_t enExtCmd[5] = {0xFF, 0x83, 0x63};
HAL_DSI_LongWrite(&hdsi, 0x00, DSI_DCS_LONG_PKT_WRITE, 4, 0xB9, enExtCmd);
uint8_t setLaneNumer[15] ={0x80, 0x00, 0x10, 0x08, 0x08, 0x10, 0x7E, 0x6E, 0x6D, 0x0A, 0x01, 0x80, 0x43};
HAL_DSI_LongWrite(&hdsi, 0x00, DSI_DCS_LONG_PKT_WRITE, 14, 0xBA, setLaneNumer);
HAL_DSI_ShortWrite(&hdsi, 0x00, DSI_DCS_SHORT_PKT_WRITE_P1, 0x36, 0x00);
HAL_Delay(7);
HAL_DSI_ShortWrite(&hdsi, 0x00, DSI_DCS_SHORT_PKT_WRITE_P1, 0xCC, 0x0B);
HAL_Delay(11);
HAL_DSI_ShortWrite(&hdsi, 0x00, DSI_DCS_SHORT_PKT_WRITE_P1, 0x29, 0x00);
After countless attempts playing around without knowing what i am doing i got the display showing something. For me it was a big success. I opened the IOC to change the touchgfx interface to Parallel RGB (LTDC) and Driver to LTDC.
DSI Host to Video Mode.
Datasheet:
- 4.0 inch diagonal display, 480 x RGB [H] x 800 [V] dots.
- 24bitRGB ( 8-8-8 Format ) / 16.7 Million colors.
- MIPI DSI as high-speed interface. Video mode only.
So far so good. I thought it would be easy now to get the timing and all the other parameters. Just use the datasheet and put the values in the correct parameter using the IOC config.
And here i started to read many many docs about LTDC, DSI and so on. But still do not understand it.
So the display is 4.0" WVGA 480 x RGB x 800 Portrait
In the dimensions part of the datasheet there is "Number of dots" 1440[H] x 800[V]. Is that something important to adjust or does that be controlled by the IC driver HX8363 ?
What about the timings? In all the datasheets some other people posted in their questions, which did not help me, the "Item" and "Symbol" is different, so it seems that every manufacturer use different namings of functions.
In my case:
And:
This is what my display actually show:
Using this settings:
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();
}
}
static void MX_DSIHOST_DSI_Init(void)
{
/* USER CODE BEGIN DSIHOST_Init 0 */
/* Activate XRES active low */
HAL_Delay(20); /* wait 20 ms */
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET);
HAL_Delay(20); /* wait 20 ms */
/* Desactivate XRES */
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_SET);
/* Wait for 11ms after releasing XRES before sending commands */
HAL_Delay(11);
/* USER CODE END DSIHOST_Init 0 */
DSI_PLLInitTypeDef PLLInit = {0};
DSI_HOST_TimeoutTypeDef HostTimeouts = {0};
DSI_PHY_TimerTypeDef PhyTimings = {0};
DSI_VidCfgTypeDef VidCfg = {0};
hdsi.Instance = DSI;
hdsi.Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE;
hdsi.Init.TXEscapeCkdiv = 4;
hdsi.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
PLLInit.PLLNDIV = 125;
PLLInit.PLLIDF = DSI_PLL_IN_DIV2;
PLLInit.PLLODF = DSI_PLL_OUT_DIV1;
if (HAL_DSI_Init(&hdsi, &PLLInit) != HAL_OK)
{
Error_Handler();
}
HostTimeouts.TimeoutCkdiv = 1;
HostTimeouts.HighSpeedTransmissionTimeout = 0;
HostTimeouts.LowPowerReceptionTimeout = 0;
HostTimeouts.HighSpeedReadTimeout = 0;
HostTimeouts.LowPowerReadTimeout = 0;
HostTimeouts.HighSpeedWriteTimeout = 0;
HostTimeouts.HighSpeedWritePrespMode = DSI_HS_PM_DISABLE;
HostTimeouts.LowPowerWriteTimeout = 0;
HostTimeouts.BTATimeout = 0;
if (HAL_DSI_ConfigHostTimeouts(&hdsi, &HostTimeouts) != HAL_OK)
{
Error_Handler();
}
PhyTimings.ClockLaneHS2LPTime = 28;
PhyTimings.ClockLaneLP2HSTime = 33;
PhyTimings.DataLaneHS2LPTime = 15;
PhyTimings.DataLaneLP2HSTime = 25;
PhyTimings.DataLaneMaxReadTime = 0;
PhyTimings.StopWaitTime = 0;
if (HAL_DSI_ConfigPhyTimer(&hdsi, &PhyTimings) != HAL_OK)
{
Error_Handler();
}
if (HAL_DSI_ConfigFlowControl(&hdsi, DSI_FLOW_CONTROL_BTA) != HAL_OK)
{
Error_Handler();
}
if (HAL_DSI_SetLowPowerRXFilter(&hdsi, 10000) != HAL_OK)
{
Error_Handler();
}
if (HAL_DSI_ConfigErrorMonitor(&hdsi, HAL_DSI_ERROR_NONE) != HAL_OK)
{
Error_Handler();
}
VidCfg.VirtualChannelID = 0;
VidCfg.ColorCoding = DSI_RGB888;
VidCfg.LooselyPacked = DSI_LOOSELY_PACKED_DISABLE;
VidCfg.Mode = DSI_VID_MODE_NB_PULSES;
VidCfg.PacketSize = 1;
VidCfg.NumberOfChunks = 200;
VidCfg.NullPacketSize = 0;
VidCfg.HSPolarity = DSI_HSYNC_ACTIVE_LOW;
VidCfg.VSPolarity = DSI_VSYNC_ACTIVE_LOW;
VidCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
VidCfg.HorizontalSyncActive = 4;
VidCfg.HorizontalBackPorch = 2;
VidCfg.HorizontalLine = 425;
VidCfg.VerticalSyncActive = 2;
VidCfg.VerticalBackPorch = 1;
VidCfg.VerticalFrontPorch = 1;
VidCfg.VerticalActive = 480;
VidCfg.LPCommandEnable = DSI_LP_COMMAND_DISABLE;
VidCfg.LPLargestPacketSize = 0;
VidCfg.LPVACTLargestPacketSize = 0;
VidCfg.LPHorizontalFrontPorchEnable = DSI_LP_HFP_DISABLE;
VidCfg.LPHorizontalBackPorchEnable = DSI_LP_HBP_DISABLE;
VidCfg.LPVerticalActiveEnable = DSI_LP_VACT_DISABLE;
VidCfg.LPVerticalFrontPorchEnable = DSI_LP_VFP_DISABLE;
VidCfg.LPVerticalBackPorchEnable = DSI_LP_VBP_DISABLE;
VidCfg.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_DISABLE;
VidCfg.FrameBTAAcknowledgeEnable = DSI_FBTAA_DISABLE;
if (HAL_DSI_ConfigVideoMode(&hdsi, &VidCfg) != HAL_OK)
{
Error_Handler();
}
if (HAL_DSI_SetGenericVCID(&hdsi, 0) != HAL_OK)
{
Error_Handler();
}
}
I have to split here because i can not send the question "Text too large".
Solved! Go to Solution.
2022-02-24 09:15 AM
Now try decrement/increment by 1
VidCfg.HorizontalSyncActive = 31;
VidCfg.HorizontalBackPorch = 31;
VidCfg.HorizontalLine = 1015;
and for rotate mirror use datasheet register command...
2022-02-22 04:39 AM
static void MX_LTDC_Init(void)
{
LTDC_LayerCfgTypeDef pLayerCfg = {0};
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;
hltdc.Init.HorizontalSync = 1;
hltdc.Init.VerticalSync = 1;
hltdc.Init.AccumulatedHBP = 2;
hltdc.Init.AccumulatedVBP = 2;
hltdc.Init.AccumulatedActiveW = 202;
hltdc.Init.AccumulatedActiveH = 482;
hltdc.Init.TotalWidth = 203;
hltdc.Init.TotalHeigh = 483;
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 = 480;
pLayerCfg.WindowY0 = 0;
pLayerCfg.WindowY1 = 800;
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB888;
pLayerCfg.Alpha = 255;
pLayerCfg.Alpha0 = 0;
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
pLayerCfg.FBStartAdress = 0xC0000000;
pLayerCfg.ImageWidth = 480;
pLayerCfg.ImageHeight = 800;
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 */
__HAL_LTDC_DISABLE(&hltdc);
DSI_LPCmdTypeDef LPCmd;
HAL_DSI_Start(&hdsi);
HX8363_Init(); // Power on sequence
LPCmd.LPGenShortWriteNoP = DSI_LP_GSW0P_DISABLE;
LPCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_DISABLE;
LPCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_DISABLE;
LPCmd.LPGenShortReadNoP = DSI_LP_GSR0P_DISABLE;
LPCmd.LPGenShortReadOneP = DSI_LP_GSR1P_DISABLE;
LPCmd.LPGenShortReadTwoP = DSI_LP_GSR2P_DISABLE;
LPCmd.LPGenLongWrite = DSI_LP_GLW_DISABLE;
LPCmd.LPDcsShortWriteNoP = DSI_LP_DSW0P_DISABLE;
LPCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_DISABLE;
LPCmd.LPDcsShortReadNoP = DSI_LP_DSR0P_DISABLE;
LPCmd.LPDcsLongWrite = DSI_LP_DLW_DISABLE;
HAL_DSI_ConfigCommand(&hdsi, &LPCmd);
HAL_LTDC_SetPitch(&hltdc, 800, 0);
__HAL_LTDC_ENABLE(&hltdc);
/* USER CODE END LTDC_Init 2 */
}
There are so many questions.
The CLK Frequency in my Display-Datasheet. is is TYP 25.0 MHz. Is this the clock "To DSI lane byte clock which is now 62.5?
The VSYNC and HSYNC frequency, in the datasheet 57.46 Hz and 48.6 Hz, where do i use that ones?
Should i start with the "MX_DSIHOST_DSI_Init" because there is a lot wrong?
I realy want to understand all the stuff, it is very interesting but hard for me.
Please help with simple words :)
Best regars,
Alex
2022-02-22 06:12 AM
Hi Alex, for learn this you need more time, maybe month. But simple steps:
2022-02-22 09:32 AM
Arguably needs a secondary school level understanding of raster displays, like the old PAL/NTSC methods, admittedly in the 1980's this was perhaps more relevant to MCU coderz
The DSI is a bitwise transfer of the pixel data as dumped into the interface by the LTDC, so DSI needs to be AT LEAST AS FAST, CAN BE FASTER. It's less fussy, as it's a transport layer, the LTDC needs to match the workable settings of the display itself.
16-bit colour depth at 62.5 MHz needs 1 Gbps bandwidth, ie 2-lanes at 500 Mbps (250 MHz DDR), the maximum of the STM32.
For 24-bit the maximum clock would be 41.67 MHz
This is further complicated by your display indicating the lane limits for it are 400 Mbps (200 MHz DDR), which would be 33.33 MHz at 24-bit, and a LTDC side perhaps at 25-32 MHz
Understand the amount of pixels displayed, and undisplayed, and the refresh rate.
The line totals include the sync, back porch, displayed pixels, and front porch. ie 528 = 16 + 16 + 480 + 16
The pixel clock = refresh rate * horizontal total * vertical total
That clock is bounded by the colour depth and DSI, and also needs to be withing min/max of actual displays capabilities.
This seems to have NO bearing on a 480(528) x 800(824) display
2022-02-23 05:28 AM
Thank you @MM..1 and @Community member for your answers,
after reading again the docs about LTDC and DSI from ST i thought i am a step further and did some calculations again.
In my case the LTDC Clock is:
LTDC_TWCR:
TOTALW: HSYNC Width + HBP + Active width HFP -1 = 527
TOTALH: VSYNC Height + VBP + Active hight + VFP -1 = 823
That results a clock of 26Mhz by: 527 x 823 x 60 Hz
This is 1) in my picture, correct?
Then, 2) is the max DSI speed, which is in my LCD Datasheet 400 ?
What about 3) and 4) in the clock configuration? In which way does that needs to be configured to the display?
@Community member You write total width and accumulated width only around 200. Why not the 800?
2022-02-23 05:31 AM
To complete it, i will attach the datasheet of the display.
2022-02-23 08:19 AM
1234 seems be ok and Tesla copies your code around 200 and meean you need correct this all values.. Logix LTDC cant have less width as Playercfg etc.
2022-02-24 07:54 AM
Thank you @MM..1
I am a bit further.
How it should look:
And how it actually looks:
I know there are a lot settings what could be the reason that it does not show correctly. But do you have any advice on how best to proceed?
Actual settings are:
hdsi.Instance = DSI;
hdsi.Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE;
hdsi.Init.TXEscapeCkdiv = 3;
hdsi.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
PLLInit.PLLNDIV = 100;
PLLInit.PLLIDF = DSI_PLL_IN_DIV2;
PLLInit.PLLODF = DSI_PLL_OUT_DIV1;
if (HAL_DSI_Init(&hdsi, &PLLInit) != HAL_OK)
{
Error_Handler();
}
HostTimeouts.TimeoutCkdiv = 1;
HostTimeouts.HighSpeedTransmissionTimeout = 0;
HostTimeouts.LowPowerReceptionTimeout = 0;
HostTimeouts.HighSpeedReadTimeout = 0;
HostTimeouts.LowPowerReadTimeout = 0;
HostTimeouts.HighSpeedWriteTimeout = 0;
HostTimeouts.HighSpeedWritePrespMode = DSI_HS_PM_DISABLE;
HostTimeouts.LowPowerWriteTimeout = 0;
HostTimeouts.BTATimeout = 0;
if (HAL_DSI_ConfigHostTimeouts(&hdsi, &HostTimeouts) != HAL_OK)
{
Error_Handler();
}
PhyTimings.ClockLaneHS2LPTime = 25;
PhyTimings.ClockLaneLP2HSTime = 27;
PhyTimings.DataLaneHS2LPTime = 13;
PhyTimings.DataLaneLP2HSTime = 20;
PhyTimings.DataLaneMaxReadTime = 0;
PhyTimings.StopWaitTime = 0;
VidCfg.VirtualChannelID = 0;
VidCfg.ColorCoding = DSI_RGB888;
VidCfg.LooselyPacked = DSI_LOOSELY_PACKED_DISABLE;
VidCfg.Mode = DSI_VID_MODE_NB_PULSES;
VidCfg.PacketSize = 480;
VidCfg.NumberOfChunks = 1;
VidCfg.NullPacketSize = 0;
VidCfg.HSPolarity = DSI_HSYNC_ACTIVE_LOW;
VidCfg.VSPolarity = DSI_VSYNC_ACTIVE_LOW;
VidCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
VidCfg.HorizontalSyncActive = 31;
VidCfg.HorizontalBackPorch = 31;
VidCfg.HorizontalLine = 1015;
VidCfg.VerticalSyncActive = 8;
VidCfg.VerticalBackPorch = 8;
VidCfg.VerticalFrontPorch = 8;
VidCfg.VerticalActive = 800;
VidCfg.LPCommandEnable = DSI_LP_COMMAND_DISABLE;
VidCfg.LPLargestPacketSize = 0;
VidCfg.LPVACTLargestPacketSize = 0;
VidCfg.LPHorizontalFrontPorchEnable = DSI_LP_HFP_DISABLE;
VidCfg.LPHorizontalBackPorchEnable = DSI_LP_HBP_DISABLE;
VidCfg.LPVerticalActiveEnable = DSI_LP_VACT_DISABLE;
VidCfg.LPVerticalFrontPorchEnable = DSI_LP_VFP_DISABLE;
VidCfg.LPVerticalBackPorchEnable = DSI_LP_VBP_DISABLE;
VidCfg.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_DISABLE;
VidCfg.FrameBTAAcknowledgeEnable = DSI_FBTAA_DISABLE;
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;
hltdc.Init.HorizontalSync = 15;
hltdc.Init.VerticalSync = 7;
hltdc.Init.AccumulatedHBP = 31;
hltdc.Init.AccumulatedVBP = 15;
hltdc.Init.AccumulatedActiveW = 511;
hltdc.Init.AccumulatedActiveH = 815;
hltdc.Init.TotalWidth = 527;
hltdc.Init.TotalHeigh = 823;
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 = 480;
pLayerCfg.WindowY0 = 0;
pLayerCfg.WindowY1 = 800;
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB888;
pLayerCfg.Alpha = 255;
pLayerCfg.Alpha0 = 0;
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
pLayerCfg.FBStartAdress = 0xC0000000;
pLayerCfg.ImageWidth = 480;
pLayerCfg.ImageHeight = 800;
pLayerCfg.Backcolor.Blue = 0;
pLayerCfg.Backcolor.Green = 0;
pLayerCfg.Backcolor.Red = 0;
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
{
Error_Handler();
}
I am using the power-on-init of the manufacturer so i don't think that there is a mistake.
What about the PHY Timings in the DSI settings? Does the display look like a DSI problem or is it more LTDC (and/or Layer) setting issue?
2022-02-24 08:07 AM
Next one step in TouchGFX designer change orientation
If your player config is 480x800 same must be TGFX and only rientation landscape/portrait
2022-02-24 08:16 AM
Well, in TouchGFX designer it is allready landscape orientation.
When i change it to portrait it has the same problems.
The photo of the display is wrong, display should be 180 flipped.
But anyway, the text is mirrored "New Text".
And the boxes should be in each corner, the stripes "RGB" from top to bottom, so many problems.
I am happy that it does show anything, but everything i change makes it worse.