DMA2D: incorrect transfer of JPEG image
Hello to everyone,
I'm working on displaying JPEG files using STM32H745BIT6 chip.
I successfully configured all peripherals (LTDC, DMA2D, HW JPEG decoder) and now I'm able to dislay JPEG data. At first JPEG decoder converts JPEG data to YCbCr data and then DMA2D converts that data to RGB and transmits it to the screen (1024x768).
Here's part of the code:
// JPEG HW decoding
JPEG_Decode(&hjpeg, (uint32_t)image_320_240_jpg, IMAGE_320_240_JPG_SIZE , (uint32_t)JPEG_OUTPUT_DATA_BUFFER);
// Waiting for the end of decoding
while(Jpeg_HWDecodingEnd == 0);
// Getting JPEG data
HAL_JPEG_GetInfo(&hjpeg, &JPEG_Info);
// Set the org of the image
xPos = 0;
yPos = 0;
// Send the image using DMA2D
DMA2D_CopyBufferJPEG((uint32_t *)JPEG_OUTPUT_DATA_BUFFER, (uint32_t *)0xC2000000, xPos, yPos, JPEG_Info.ImageWidth, JPEG_Info.ImageHeight, JPEG_Info.ChromaSubsampling);Here's the screen:
The only problem is when X-coordinate of the image makes it to be out of the screen area, the "outer" part of the image is showing at the begining of the screen.
For example, if xPos == 800 then the screen is:
How to avoid this "tail drawing"?
I guess something is missing in DMA2D transfer function.
Here's the code:
void DMA2D_CopyBufferJPEG(uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize, uint32_t ChromaSampling)
{
uint32_t cssMode = LL_DMA2D_CSS_420, inputLineOffset = 0;
uint32_t destination = 0;
uint16_t LCD_X_Size;
while (DMA2D->CR & DMA2D_CR_START);
LCD_X_Size = 1024;
if(ChromaSampling == JPEG_420_SUBSAMPLING)
{
cssMode = LL_DMA2D_CSS_420;
inputLineOffset = xsize % 16;
if(inputLineOffset != 0)
{
inputLineOffset = 16 - inputLineOffset;
}
}
else if(ChromaSampling == JPEG_444_SUBSAMPLING)
{
cssMode = LL_DMA2D_CSS_444;
inputLineOffset = xsize % 8;
if(inputLineOffset != 0)
{
inputLineOffset = 8 - inputLineOffset;
}
}
else if(ChromaSampling == JPEG_422_SUBSAMPLING)
{
cssMode = LL_DMA2D_CSS_422;
inputLineOffset = xsize % 16;
if(inputLineOffset != 0)
{
inputLineOffset = 16 - inputLineOffset;
}
}
/*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/
LL_DMA2D_SetMode(DMA2D, LL_DMA2D_MODE_M2M_PFC);
LL_DMA2D_SetOutputColorMode(DMA2D, LL_DMA2D_OUTPUT_MODE_RGB565);
LL_DMA2D_SetLineOffset(DMA2D, LCD_X_Size - xsize);
LL_DMA2D_FGND_SetColorMode(DMA2D, LL_DMA2D_INPUT_MODE_YCBCR);
LL_DMA2D_FGND_SetAlphaMode(DMA2D, LL_DMA2D_ALPHA_MODE_REPLACE);
LL_DMA2D_FGND_SetAlpha(DMA2D, 0xFF);
LL_DMA2D_FGND_SetLineOffset(DMA2D, inputLineOffset);
LL_DMA2D_FGND_SetRBSwapMode(DMA2D, LL_DMA2D_RB_MODE_REGULAR);
LL_DMA2D_FGND_SetAlphaInvMode(DMA2D, LL_DMA2D_ALPHA_REGULAR);
LL_DMA2D_FGND_SetChrSubSampling(DMA2D, cssMode);
destination = (uint32_t)pDst + ((y * LCD_X_Size) + x) * 2;
LL_DMA2D_FGND_SetMemAddr(DMA2D, (uint32_t)pSrc);
LL_DMA2D_SetOutputMemAddr(DMA2D, destination);
LL_DMA2D_SetNbrOfPixelsPerLines(DMA2D, xsize);
LL_DMA2D_SetNbrOfLines(DMA2D, ysize);
LL_DMA2D_Start(DMA2D);
while (DMA2D->CR & DMA2D_CR_START);
}What am I doing wrong?
Thanks for your attention.