This article describes the frame rate of a TouchGFX application.
The TFT controller in the microcontroller automatically updates the LCD screen at regular intervals. This interval is dependent on the microcontroller and the LCD but it is normally 50 - 60 Hz (or every 16 - 20 ms). We call this the LCD update rate.
The TFT controller synchronizes these updates with the application through a VSYNC interrupt which is raised just before the update starts.
On a system with two frame buffers the TouchGFX framework swaps to the other frame buffer if anything new has been drawn, and the GUI thread will start drawing in the old frame buffer.
This is illustrated in the drawing below:
At the points a, c, and e, the TFT controller transfers the framebuffer to the LCD.
A point b, the drawing of a screen is complete. This screen is not shown before point c, where the frame buffers are switched.
Point d illustrates a very short drawing routine that does not draw anything. Because nothing new is drawn TouchGFX does not swap framebuffers at point e.
TouchGFX will call all tick methods (e.g. on your Model class) and all event handlers of the current Screen (e.g. handleTickEvent()) before drawing the screen.
This allows you to update your model or implement animations (e.g. simple clock hands) on the screen.
The tick method calls and the subsequent drawing in the frame buffer are normally performed once for every LCD update. This gives us an application frame rate equal to the LCD update rate (60 Hz). In other words, we can draw new graphic on every update LCD update.
Long draw operations
In some cases the draw operation of a screen will take longer time than available between the LCD updates. This is illustrated in the figure below:
The drawing operation (rendering) ends after the third VSYNC and the graphics is shown when swapping the frame buffers on the fourth. This means that the application frame rate is one third of the LCD update rate.
If this only happens occasionally, the problem can often be ignored, but if you have a complex screen this may happen on every frame.
Compensating for reduced frame rate
The tick methods are called once for each call of draw. That is, one tick for each new frame. In case of having frames that occasionally take a long time to render, the tick frequency may be irregular.
As mentioned the periodic tick can be used to implement animations: Say for example that we need an icon to move 200 pixels across the screen in ~3 seconds. If the LCD update rate is 60 Hz (corresponding to 16.7 ms) we need to move the icon 1 pixel in every frame.
This will work nicely if the drawing operations can complete within the 16.7 ms. If the drawing operation takes longer than that, we will miss the next LCD update and the frame rate is reduced. Usually this is not a big problem, as you would then just modify the animation to, e.g. move the icon 2 pixels in every frame. In this case, the animation would still complete in 3 seconds. But it will be problematic in cases where the tick rate is irregular - i.e. sometimes the tick rate is 16.7ms and sometimes it is 33ms as it would cause the animation to look uneven, and the duration would be unpredictable.
To alleviate this, TouchGFX has a "reduced frame rate" compensating feature that relieves this problem. When enabled it will make an additional call to tick for each missed LCD update. and the rate of calls to tick will thus match the LCD update rate.
- FrameRateCompensation was introduced in TouchGFX release 4.5.0
In the above example the tick method will be called 3 times prior to calling draw after the long running draw operation. It is now sufficient to move the icon 1 pixel in tick.
Frame rate compensation is as default disabled.
You can enable it by calling the setFrameRateCompensation method in HAL:
If you need this as a general setting for you application it is recommended to insert the call in touchgfx_init() in BoardConfiguration.cpp. Otherwise it can be enabled/disabled on a per-View basis.
You can also get the number of missed frames for a given tick by calling the getLCDRefreshCount method in HAL:
This can be used to skip time consuming actions in the tick method by checking the size of the LCDRefreshCount. It will be equal to the number of draws that has been executed since the last tick, which, in the case of FrameRateCompensation, will be equal to the number of ticks that will be executed in this frame.