cancel
Showing results for 
Search instead for 
Did you mean: 

Port TouchGFX to FMC with ILI9341

PCu1
Senior

Hello,

I developed a STemwin project a few years ago, with an STM32F437 and an LCD(320x240) driven in FMC with the ILI9341 controller.

I am looking to migrate this card to touchGFX for a different application.

But I have an issue:

If the screen is static, there is no problem.

In the screen below I have an animated image, but the image doesn't turns.

However the code enters continously in TouchGFXHAL::flushFrameBuffer(), so far so good.

Expected:

0693W000006G9c5QAC.png 

I did an other screen where a circle moves but it renders bad in movement. The first image is correct.

I think there is a problem with the offset when the program reenter in flushFrameBuffer(), because with rect.x and y at 0, what is displayed is correct.

This is the code :

void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect)
{
    // Calling parent implementation of flushFrameBuffer(const touchgfx::Rect& rect).
    //
    // To overwrite the generated implementation, omit call to parent function
    // and implemented needed functionality here.
    // Please note, HAL::flushFrameBuffer(const touchgfx::Rect& rect) must
    // be called to notify the touchgfx framework that flush has been performed.
 
    //TouchGFXGeneratedHAL::flushFrameBuffer(rect);
 
	//dma.flush();
 
	HAL::flushFrameBuffer(rect);
 
	/* Set Cursor */
	__ILI9341_SetDisplayWindow(rect.x, rect.y, rect.width, rect.height);
	
	/* Prepare to write to LCD RAM */
	LCD_IO_WriteReg(0x2C);
 
	/* Read dummy data */
	LCD_IO_ReadData();
 
	this->copyFrameBufferBlockToLCD(rect);
}
 
void TouchGFXHAL::copyFrameBufferBlockToLCD(const Rect rect)
{
    __IO uint16_t* ptr;
    int16_t height;
 
    // Use default implementation (CPU copy!).
    // This can be accelerated using regular DMA hardware
    for (height = 0; height < rect.height ; height++)
    {
        ptr = getClientFrameBuffer() + rect.x + (height + rect.y)  * 320;
        LCD_IO_WriteMultipleData((uint16_t*)ptr, rect.width);
    }
}
 
    __weak void __ILI9341_SetDisplayWindow(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
    {
        LCD_IO_WriteReg(0x2A);
        LCD_IO_WriteData(Xpos / 256);
        LCD_IO_WriteData(Xpos % 256);
        LCD_IO_WriteData(Width / 256);
        LCD_IO_WriteData((Width % 256) );
 
        LCD_IO_WriteReg(0x2B);
        LCD_IO_WriteData(Ypos / 256);
        LCD_IO_WriteData(Ypos % 256);
        LCD_IO_WriteData(Height / 256);
        LCD_IO_WriteData((Height % 256) );
    }

Thank you for your help.

4 REPLIES 4
PCu1
Senior

After reading some other posts:

The display TE pin is not connected to my processor. I call TouchGFX_TickHandler() in a timer INT at 60Hz. Can I do like this?

With Stemwin it worked but the strategie to manage the frame buffer is may be different (always entire buffer in STemwin vs partial in TGFX ???)

Is there an option to refresh the entire buffer in TGFX if it could be a solution(with less perfomance of course).

Thank you

PCu1
Senior

I found a workaround to refresh all the screen (variable rectAll:(

void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect)
{
    // Calling parent implementation of flushFrameBuffer(const touchgfx::Rect& rect).
    //
    // To overwrite the generated implementation, omit call to parent function
    // and implemented needed functionality here.
    // Please note, HAL::flushFrameBuffer(const touchgfx::Rect& rect) must
    // be called to notify the touchgfx framework that flush has been performed.
 
	//dma.flush();
 
	//Workaround: Force refresh all frameBuffer
	touchgfx::Rect rectAll = {.x = 0, .y = 0, .width = 320, .height = 240};
 
	HAL::flushFrameBuffer(rectAll);
 
	/* Set Cursor */
	__ILI9341_SetDisplayWindow(rectAll.x, rectAll.y, rectAll.width, rectAll.height);
 
	/* Prepare to write to LCD RAM */
	LCD_IO_WriteReg(0x2C);
 
	/* Read dummy data */
	LCD_IO_ReadData();
 
	this->copyFrameBufferBlockToLCD(rectAll);
}

It works until now and it seems enough smoothie for my application.

But I don't explain why I can't refresh a partial buffer...

MM..1
Chief

I mean your failure is not accept partial buffering , when you generate code then here is

void TouchGFXGeneratedHAL::flushFrameBuffer(const touchgfx::Rect& rect)
{
    HAL::flushFrameBuffer(rect);
 
    // Once flushFrameBuffer() is called by the framework a block is ready for transfer
    // Mark it ready for transfer and transmit it if user defined method 
    // isTransmittingData() does not return false
    
    // If data is not being transmitted, transfer the data with user defined method
    // transmitFrameBufferBlock().
    frameBufferAllocator->markBlockReadyForTransfer();
    if (!isTransmittingData())
    {
        touchgfx::Rect r;
        const uint8_t* pixels = frameBufferAllocator->getBlockForTransfer(r);
        transmitFrameBufferBlock((uint8_t*)pixels, r.x, r.y, r.width, r.height);
    }
}

as you see this called first HAL flush, then transmit first partial block, and next blocks is managed as describe Lowering Memory Usage with Partial Framebuffer | TouchGFX Documentation

Yes I think the partial refresh is not available(or not well configured) in the Display.

So, I refresh the entire screen as mentioned and this is not an issue for this project because there is no animation.