cancel
Showing results for 
Search instead for 
Did you mean: 

Touchgfx Double Frame Buffer Custom SPI Interface Example

farukisiker
Associate III

Hello,

I drived lcd by using partial frame buffer. Now, I am trying to update it with double buffer strategy. The LCD has TE pin that helps checking Vsync.

I could not find a clear example for double buffering method. I don't need FMC since internal ram is enough for driving.

Do you have any example or steps that I need to follow for those specs:

Touchgfx with double buffer + FreeRTOS (CMSIS V2) + SPI LCD (With TE pin) 

 

Touchgfx Version : 4.25.0

CubeIde Version : 1.17.0

MCU : H7 series

Best regards,

Faruk

1 ACCEPTED SOLUTION

Accepted Solutions
JohanAstrup
ST Employee

Yes, that is possible. Among the TBSs available in TouchGFX Designer, I recommend looking at either NUCLEO-H563ZI + GFX02Z1 or NUCLEO-U575ZI + GFX02Z1. Both of these are running with an 8080 display. The main difference for you, however, is that you need to replace the call to LCD_IO_SendDataDMA() in LCD_SignalTearingEffectEvent() in TouchGFX.cpp with HAL_SPI_Transmit_DMA().

Bear in mind that the DMA can transfer a maximum of 65535 bytes in a single transfer. Therefore, you must split your framebuffer transfer into at least three smaller transfers. Alternatively, you can use the DMA in linked-list mode, as implemented in the TBSs mentioned above.

Best regards,
Johan

View solution in original post

9 REPLIES 9
JohanAstrup
ST Employee

Hello @farukisiker.

Which controller does your display have? And what color depth are you targeting?

One of the reasons there are no examples available for double buffering with an SPI display is that there are few combinations of display size, display controller maximum speed, and MCU SPI maximum speed capable of updating the entire display within one frame (~16 ms).
However, since you are using an H7 and have a relatively small display, it might be possible for you, depending on the maximum frequency the display controller can handle.

Best regards,
Johan

Hello @JohanAstrup ,

The display driver is st7789v2 which has max SPI speed around 62Mhz. The color depth is 16bit which is RGB565. The display size is 240x280. 

Is it possible to use double buffering in this case? If yes, could you provide a clean example or steps that I need to follow for implementation?

Best regards,

Faruk

JohanAstrup
ST Employee

OK, thanks for the info. Then, assuming there is no overhead, we can do the following calculations:

1. Calculate the number of bits that can be transferred in one tick (~16 ms):
62Hz * 10^6 * (1 / 60FPS) = 1.033.333 bits

2. Calculate the number of bits in a framebuffer:
240px * 280px * 16bpp = 1.075.200

Since the number of bits in the framebuffer exceeds the number of bits that can be transferred on SPI within one tick, achieving 60 FPS is not possible if double framebuffers are implemented in the usual way.

There are ways to work around this, though. You can implement custom code to transfer only the parts of the framebuffer that have been updated/rendered. This can be achieved using different methods with varying levels of complexity. For the simplest implementation, refer to the flushFrameBuffer function in TouchGFXHAL.cpp in the NUCLEO-U575ZI + RVA35HI TBS available in TouchGFX Designer. In this implementation, the minimum and maximum updated lines in the framebuffer are calculated, and only the area in between is transferred. However, this approach will not help if pixels in both the first and last lines of the framebuffer are updated.
You can enhance performance further at the cost of increased complexity by calculating the actual rects of the framebuffer that are updated and transferring only these. However, in any case, you cannot achieve 60 FPS if the entire framebuffer is updated.

The optimal framebuffer strategy depends on the system setup. Since you are using H7, which is a quite powerful MCU, your primary limitation is most likely the bandwidth to the display. Therefore, the most suitable framebuffer strategy might be to continue using partial framebuffer. By using a partial framebuffer, you essentially benefit from the previously mentioned method of transferring only the updated framebuffer blocks. However, the downside of this approach is that it will not perform well with SVGs and some Canvas Widgets.

Best regards,
Johan

 

 

@JohanAstrup thanks for detailed explanation.

What if I run my display at 50Hz?

62 000 000 / 50 = 1 240 000 bits.

I think that it seems possible theoratically. If I use it in 50Hz, could you recommend me an example?

 

Best regards,

Faruk

JohanAstrup
ST Employee

Yes, that is possible. Among the TBSs available in TouchGFX Designer, I recommend looking at either NUCLEO-H563ZI + GFX02Z1 or NUCLEO-U575ZI + GFX02Z1. Both of these are running with an 8080 display. The main difference for you, however, is that you need to replace the call to LCD_IO_SendDataDMA() in LCD_SignalTearingEffectEvent() in TouchGFX.cpp with HAL_SPI_Transmit_DMA().

Bear in mind that the DMA can transfer a maximum of 65535 bytes in a single transfer. Therefore, you must split your framebuffer transfer into at least three smaller transfers. Alternatively, you can use the DMA in linked-list mode, as implemented in the TBSs mentioned above.

Best regards,
Johan

Instead of using linked-list mode, is it possible to use dma buffer size in 32 bit mode? 

JohanAstrup
ST Employee

To my knowledge, the DMA is limited to 65535 bytes in each transfer regardless of the size of the input data. If you do not want to use linked-list mode, which can be a bit cumbersome to set up, I recommend controlling it manually by splitting the transfer into smaller transfers of maximum 65535 bytes. In the DMA callback, initiate a new transfer for the next part of the framebuffer if the entire framebuffer has not been transferred yet.

Best regards,
Johan

@JohanAstrup thanks for answer.

Splitting frame buffer made tearing effect. So I tried to use MDMA and linked list to send big data.Firstly I debug it for uart peripheral. After sending 16 bytes, uart dr gets locked.

Actually, I could not find any good example for mdma. Could you recommend me clear example for MDMA usage? For example; how to configure it in .ioc file, how to start it, how to write data to peripheral data transmit register... ?

Best regards,

Faruk

JohanAstrup
ST Employee

If you experience tearing when splitting the framebuffer, you will most likely also experience tearing when using the linked-list mode. The issue is rather that it is still not possible to transfer a full frame within one tick or missing synchronization between the framebuffer transfer and the display refresh.

Have you measured the display refresh rate and the actual time it takes to transfer a full frame? The calculation above only provides the theoretical bandwidth, assuming no overhead.

I recommend looking at the H7 Cube firmware MDMA examples. There are e.g. three available MDMA examples for the STM32H735G-DK, including one demonstrating MDMA linked-list.


Best regards,
Johan