tft lcd frame buffer in stock

I am using STM32H753 for driving 800x480 TFT LCD. Currently I am using External SDRAM for my FRAME BUFFER. I am using DMA2D and TFT LCD module of MCU.

tft lcd frame buffer in stock

I"m talking about some nxp mcu like lpc1788 with the lcd controller integrated into the chip so you don"t need to use an external lcd controller. The models you are listing don"t have the lcd controller integrated,.

The main advantage of having it external is that the lcd controller has got its own memory for the frame buffer and it"s easing the load on the cpu because once you load the data it will keep refreshing the screen without calling the cpu and it doesn"t use the cpu ram memory.

In the other case if the lcd controller is integrated in the mcu you can do some nice "tricks" like using a colour look up table or palette so that your graphics takes less memory and because the framebuffer is in your internal memory it is even easier to manipulate.

Also consider that in case of lcd controller not integrated in the panel (so by using the one integrated in the mcu or another one on board as a separate chip) you can exchange panel quite easily so you are not tied to a single manufacturer as long on the lcd side you find the same interface like the 24 bit or the 18 bit.

Now, I"m considering the case of an lcd panel of 640x480 and 8 bit per colour which leads us to 640x480x8 = 2457600 bit / 8 = 307200 / 1024 = 300 KByte of ram needed for the framebuffer.

The integrated lcd controller has got a dma which will take care of transferring the data from external ram used for the frambuffer to the lcd controller which will then translate it and send to lcd but the problem is that the external bus and also the internal bus of the mcu(difficult to draw this here :-) ) is then shared by the lcd controller, which keeps accessing the memory to continuously refresh the screen, and the mcu which is fetching instructions or variables.

Because the internal bus gives priority to the mcu it means that probably you will see tearing effect on the lcd like reported by some people on the nxp question and answer (pasting the link here takes you to the general support page and not to the answer I found) because the mcu gain priority when accessing bus and memory and lcd refresh is delayed.

In the answer I found on Nxp support, they say you can actually change priority so that lcd screen has an higher priority then the cpu, problem is that in doing so the cpu and then your software will be slowed down by the lcd controller continuously refreshing and accessing memories.

tft lcd frame buffer in stock

In chapter 7, we made use of the segmented LCD display on the Wonder Gecko Starter Kit through the use of a pre-built LCD library and driver when designing the user interface for the sprinkler timer. That made things easy for us, and we didn’t really need to dwell on how the driver worked. In this chapter, we will dig into some of those details so that we can connect the EFM32 to any kind of display we choose.

The display we will be using for this chapter is the Adafruit 2.8” 240x320 TFT LCD Capacitive Touch screen, shown below. We will interface with it over SPI for transferring image data and I2C for reading the touch interface. We will learn how to interface with it with our own drivers and build our own simple graphics libraries, as well.

Segmented Display: We have already worked with the segmented LCD display in chapter 7, also known as a character display. In such a display, there are a fixed matrix of LCD segments that are preconfigured in hardware to convey specific information. They are not flexible enough to display an image, but they don’t require many pins on the MCU and are easier to program. For example, the number “9” can be formed on such a display with as few as 6 signals.

Note that a new “Memory LCD” described in Silicon Labs application note AN0048 couples a memory device within each pixel so that constant refreshing is not necessary, reducing power consumption as well.

Graphical display screens have many different technologies, from passive-matrix Liquid Crystal Display (LCD) or active-matrix Thin Film Transistor (TFT) LCD, Light Emitting Diode (LED), or Organic LED (OLED). Display technology is not the focus of this chapter. No matter which technology you choose, you will still need to understand the topics of this chapter in order to display your images.

The LCD pixel matrix is the heart of the display. This part is responsible for displaying the image and, in the case of LCD displays, it will either allow or prevent light from a backlight to pass through. In the case of LED displays, the pixel matrix produces the light and forms the image in one step. No matter the process, the pixel matrix is comprised of an array of pixels in height and width of a certain color depth that make up the display. For the display used in this chapter, the color depth is 18 bits, consisting of 6 bits each for the red/blue/green components of a pixel. That means that the information required to paint the screen one time is 240 bits wide x 320 bits tall x 18 bits of color = 172,800 bytes. That’s a lot of data, and it is more data than we can hold in the RAM of the Wonder Gecko MCU. Therefore, it will require some intelligent code to drive the display or an external memory buffer to store the image data.

The backlight is necessary for TFT LCD displays to allow the display to be seen. Without a backlight, a color TFT LCD will show no image. A monochrome LCD is a little different, since the segments can be seen if they are in the “on” state. The brightness of an LCD screen is sometimes controlled by applying a Pulse Width Modulated (PWM) signal to a pin (or pins) that controls the LED backlight. This is exactly what we have already done in the last chapter to dim an LED.

A frame buffer is a block of RAM that holds all of the color information for every pixel (172 kB for this display) that is used to paint a single image (or “frame”) to the display. This buffer is required to exist somewhere in the system because it is used by the display driver chip to refresh the LCD image many times per second.

In a general sense, all display architectures require the above control blocks. The display contains a number of scan lines (depending on the resolution) and an image driver that must continually feed the scan control circuitry with pixel data, even for a static image. The pixel control allows light to pass for an instant, and then the pixel goes dark again. If the scan control circuitry were stopped, the display would turn dark, as all pixels would be turned off. Therefore, the image driver needs a frame buffer of memory somewhere in the system to fetch the pixel data that is needed for every scan. The application fills the frame buffer as new drawing operations change what is to be displayed on the screen.

In the RGB interface mode, the MCU acts as the image driver. This means that it must constantly drive data to the display, refreshing all 320 x 240 pixels many times per second. You can imagine the amount of work that would require of your MCU. If the frame buffer is too big to fit in the MCU RAM, an external memory chip must be used. The frame buffer can be attached to the MCU via serial interfaces such as I2C or SPI for static images such as device menus, but must utilize a parallel interface in order to keep up with the demands of full motion video. The External Bus Interface (EBI) can be used with external memory for maximum speed and ease of use, as long as your particular model of EFM32 supports it. EBI extends the RAM of your EFM32 and allows you to address external memory as if it resides within the RAM address space of the EFM32 itself.

When a display has an integrated device driver chip and frame buffer (such as the Ilitek ILI9341 used in this chapter), the MCU doesn’t have to perform all of the constant refreshing of the display; it only sends data to the driver chip when the image changes. This enables the MCU to offload all of that work to stay focused on the application at hand rather than driving the display.

At the bottom of the software stack, the device driver is the necessary code that customizes your graphics library for your particular display device architecture and physical hardware connection. (Note that a software device driver is not the same thing as the device driver chip on the physical display.) Graphics libraries are flexible, and can be adapted to many different display architectures, but they need to be configured for your display architecture and MCU. The device driver provides this customization, providing the display’s resolution and color depth, mapping the data bus for the display to GPIO pins on your MCU and setting up the memory for the frame buffer (if applicable).

tft lcd frame buffer in stock

Large amounts of pixel data are used to create the colorful and defined images. The data is stored in a memory location called the frame buffer. The frame buffer must be provided by the display or by the processor. The MIPI DSI interface offers an alternative by operating the display in video mode.

This resource will discuss the options for storing large amounts of image data and the operating modes available in the MIPI DSI communication protocol. There are two modes available when memory is accessible to the display. The modes are differentiated by the location of frame buffer provided for display data. The substitute for display memory is to operate the display in video mode which does not require memory access. Considerations of memory location and access should be made when using the MIPI DSI protocol.

High resolution displays have a larger number of pixels and require more memory. An increased color depth means there is more data assigned to each pixel. For true color (RGB-888) each pixel is assigned 24-bits of color. This data needs to be stored in a location accessible by the microprocessor and the display. The minimum memory requirement for the framebuffer is calculated by the following equation.

This is the memory for one full frame of image data. There are options for efficiently storing display data and maximizing available memory. A lower color resolution can be set with minimal reduction or visible effect on the image. Partial image storing is another way to conserve memory. The frame buffer will contain a portion of the frame that is to be updated. This can be referred to as layering and only certain layers are refreshed.

The location of the frame buffer memory is dependent on what is available and what can be accessed at a speed compliant with the MIPI DSI interface. The MIPI DSI display interface requires high speed memory access to prevent flickering and tearing on the display. Each location of memory has its own benefits and constraints. The display memory can be stored in the following locations for the MIPI DSI interface.

The display memory is customizable by location, amount available and the desired display application. Pixel data can be stored in partial frames to conserve memory. The images can be programmed in independent layers to minimize the amount of data that needs to be refreshed. The layers can be stored in different memory locations on the processor which provide more accessible memory for image data.

The frame buffer can be stored in the internal display RAM and accessed by the display controller IC. The image data is written to display RAM by the controller through specified commands. Other commands are used to specify color format, voltage settings and data types. In this scenario, the display does all of the heavy lifting. This frees up the microprocessor for other processes and the display can operate while the MPU is idle.

Another benefit of using internal display RAM is that the physical memory addresses correspond to the pixel display area. In other words, the frame buffer is the same size as the resolution. The internal display RAM provides the exact amount of memory for the display resolution. This makes reading and writing to RAM simple. Display RAM typically provides enough memory for one full page of image data at high color. This can often be more than what is provided on the MPU.

The MIPI DSI protocol has two operation modes. The command mode is used when the display has access to the internal frame buffer memory. The display controller receives commands from the processor and then formats the data to store in the frame buffer for the next display refresh.

The display is operated by specified commands that will address the memory of the frame buffer internally. The commands are sent over a low power and short packet data type. These commands will initialize the driver to handle the data. The data can be sent in long packets at high speeds to be stored in internal memory and accessed for the next fresh cycle.

Internal RAM is a limited resource for many processors. Most processors will not have the memory available for a full page of display data especially at high resolutions and high color formats. Steps can be made to maximize available MPU memory usage. Display data can be stored in layers that make up portions of the full frame. Updating smaller portions of the display can conserve memory instead of storing and continuously updating the full frame.

Storing data in partial frame buffers reduces the amount of memory stored in RAM but requires more drawing operations to be performed between the display and the processor. The means that more transfers to the display are needed and thus a faster interface clock is required.

A lower color format can be chosen without a significant reduction to image quality . The color format of the frame buffer determines how much memory is required for the page. The memory required for the frame buffer of a 400x800 pixel display with 24bpp color depth is 1.5MB. At 16bpp, RGB-565, the memory required for the same resolution is reduced to 768kB. Different layers and partial frames can be programmed to have independent color formats.

Video mode places more demand on the host processor. The processor is continuously streaming the pixel data which requires a higher bandwidth. Synchronization timing events need to be calculated and implemented into the high-speed packets of display data to properly frame the image.

The video mode of the MIPI DSI communication protocol consumes more power than the low power command mode. The high-speed video mode can incorporate low power transition times between lines or frames to conserve power while synchronizing the display data. The low power modes indicate the begin and end flags of packet data.

In cases where internal RAM is not used, external RAM can be incorporated into the system. External RAM provides more memory than the internal systems. Storing the frame buffer in external memory can be slower to access than to internal memory. The processor will have to access the external RAM and forward the information to the display at a speed fast enough to maintain the minimum frame rate requirements.

Using external RAM allows for multiple buffers to be incorporated into the system. Since there is enough memory available, multiple buffers can be stored to increase performance. Using multiple frame buffers allows for queuing multiple pages of data. This can be beneficial for rendering speeds.

The MIPI DSI video mode will be used to send external RAM continuously to the display. This will increase the required MPU frequency to retrieve and send display data to and from RAM. Processor memory is not sacrificed when implementing an external memory to store the frame buffer.

An external memory that is interfaced with the host processor can have timing constraints in maintaining the speeds required to read and write the frame buffer. The frame buffer is stored in RAM and not FLASH because it requires a continuous update. The desired bitmaps or fonts (general display data) are stored in FLASH memory to be sent to RAM for the next display update.

When selecting external RAM for display memory, considerations should be made toward power consumption and performance. SRAM provides the fastest access to the framebuffer to avoid timing issues such as flickering or tearing on the display.

Buyers and others who are developing systems that incorporate FocusLCDs products (collectively, “Designers”) understand and agree that Designers remain responsible for using their independent analysis, evaluation and judgment in designing their applications and that Designers have full and exclusive responsibility to assure the safety of Designers" applications and compliance of their applications (and of all FocusLCDs products used in or for Designers’ applications) with all applicable regulations, laws and other applicable requirements.

Designer agrees that prior to using or distributing any applications that include FocusLCDs products, Designer will thoroughly test such applications and the functionality of such FocusLCDs products as used in such applications.

tft lcd frame buffer in stock

If you’re running a console on the same framebuffer, you’ll find the text cursor displays over whatever you’ve painted. This is because the console is also updating the framebuffer, and in particular, it’s updating the framebuffer periodically. So, if you paint something to the screen, the console application will overwrite just the part of memory where the cursor is meant to appear.

It is possible to disable the cursor, though if you want to restore the cursor when exiting your application, you have to keep your application running until you’re ready to relinquish control. I haven’t yet figured out how to disable the cursor, but other framebuffer applications do this all the time.

tft lcd frame buffer in stock

The cliff notes version is: GPUs have their own memory, which is directly visible to the CPU in the form of a memory mapping (you can query the actual range of physical addresses from e.g. /sys/class/drm/card0/device/resource). Somewhere in there, there"s also the memory used for the display scanout buffer. When using GPU accelerated graphics, the GPU will write directly to those scanout buffers – possibly to memory that"s on a different graphics card (that"s how e.g. Hybrid graphics work).

If this is a TFT display connected with SPI or an parallel bus made from GPIOs, then yes, there"ll be some memory reserved for the image to reside on. Strictly speaking this can be in the RAM for the CPU, or in the VRAM of a GPU, if there is one. However as far as latencies go, the copy operations for scanout don"t really matter these days.

tft lcd frame buffer in stock

The STM32 LTDC has a peripheral called LTDC LCD TFT Display Controllerwhichprovides a digital parallel interface(DPI) for a variety of LCD and TFT panels. It sends RGB data in parallel to the display and generates signals for horizontal and vertical synchronization (HSYNC, VSYNC), as well as pixel clock (PCLK) and not data enable (DE) signals:

The LTDC has two layers which can be configured, enabled and disabled independently, each with its own FIFO buffer. Layer order is fixed and layer2 is alway on top of layer1. Layer can be enabled writing the LEN Layer Enable bit in the LTDC_LxCR Layer x Control Register. Each layer gets its data from a framebuffer in memory and the start address is written in LTDC_LxCFBAR Layer x Color Frame Buffer Address Register. The frame buffer contains the display frame data in one of eight configurable pixel format: LTDC_LxPFCR Layer x Pixel Format Configuration Registeris configured to choose the pixel format used to store data into the frame buffer. The available pixel formats are:

The frame buffer has a configurable line length (in bytes) in the LTDC_LxCFBLR Layer x Color Frame Buffer Length Register  and a configurable total number of lines in the LTDC_LxCFBLNR Layer x Color Frame Buffer Line Number Register. It also has a configurable line pitch, which indicates the distance in bytes between the start of a line and the beginning of the next line, also configured in the LTDC_LxCFBLRregister, and expressed in bytes. These parameters are used by the LTDC to fetch data from the frame buffer to the layer FIFO. If set to less byte than needed, a FIFO underrun interrupt will trigger (if enabled), if set to more bytes than required the rest of the data loaded into the layer’s FIFO is discarded.

Line length parameter is the number of bytes in a line plus three (so the total line length is number of pixels * bits per pixel + 3). These parameters, together with the layer windowing settings, are useful if we want to display part of an image contained in the frame buffer, as I’ll show later.

In this example I use the display on the STM32F429-Discovery board, which is driven by the ILI9341 display controller. The ILI9341 can drive a QVGA (Quarter VGA) 240×320 262,144 colors LCD display. The controller can be configured via SPI (or parallel interface, depending on the panel settings) to use a digital parallel 18 bit RGB interface (since only 6 lines per color channel are wired on the board to the LTDC). Since the display pixel format is less than 8 bit per channel (RGB666 in this case), the RGB display data lines are connected to the most significant bits of the LTDC controller RGB data lines:

Before enabling the LTDC we must configure the clock system. The LTDC uses a specific clock LCD_CLOCK to generate the pixel clock signal and it must be configured and enabled during the system initialization phase:

To display an image we must convert an image file to an array (possibly a const one, so it can be stored in flash memory) of bytes. To do this I used LCD image converter, a simple but powerful application that can convert a file to a variety of different pixel formats:

Once the image is converted to a byte array the generated header file is included and the array address can be used as the frame buffer starting address in the LTDC_LxCFBAR register. Layer window parameters are configured according to the image size (240 x 320, I rotated the image to fit the display in portrait mode).

Now I’m just showing 100 x 100 pixels of the layer 1 image so I configured the color buffer line length as 100 and the color buffer number of lines as 100. The line pitch value indicates that a framebuffer line is still 240 * 3 bytes long so the controller knows how to fetch bytes from the frame buffer correctly. I also moved the start of the window adding an offset of 50 pixels and 50 scan lines. The default background color is used where the layer isn’t used (the layer background color is a solid green):

Using two layers and playing with the layer window size and position allows to create simple animations by simply moving the layer window around the frame:

Shadow configuration registers are reloaded each vertical blanking period (after the last line has been drawn) and the code waits for the next frame by polling the VSYNCS flag of the LTDC_CDSR Current Display Status Register, whose bits contain the state of the synchronization signals (high if they’re asserted, no matter the polarity configured). Running the code we get a nice smooth animation:

Double buffer is used when we want the code to write on a frame buffer while another buffer is being read by the LTDC. This avoids corrupting the data being displayed on the screen. The buffers are switched during the vertical blanking period using polling or interrupts.

figure n: while the code writes to the back buffer the LTDC fetches data from the front (active) buffer. Famebuffers are switched during vertical blanking period.

In this example the framebuffers have a RGB888 color depth and for a 240×320 display that makes 225 KiB of memory for each buffer (3 bytes per pixel x 240 x 320 pixels) so they must be stored in external SRAM (the STM32F429I-DISCOVERY has a 64Mbit external SRAM so we’re good). The FMC Flexible Memory Controller has to be initialized and the address of the two frame buffers has to be configured. Drawing on the framebuffer is a matter of writing the right bytes in order to change the color. Once all pixels are drawn (bytes are written) the buffers are switched and the code can draw the next frame:

Now as soon as a frame is done with, calling LTDC_switch_framebuffer() waits for the vertical synchronization period and swaps the buffers. If the code is faster than the display refresh rate (70Hz in our case) it waits for the LTDC to complete drawing the frame.

tft lcd frame buffer in stock

Digital Blocks TFT LCD Controller reference design enables you to accelerate the design-in of TFT LCD panel displays in your system. The reference design centers on the Digital Blocks DB9000AVLN TFT LCD Controller intellectual property (IP) core, which is available in netlist or VHDL/Verilog HDL register transfer level (RTL) formats.

The DB9000AVLN core contains an Avalon® Memory-Mapped system interconnect for interfacing to the Nios® II embedded processor and SDRAM or SRAM controllers (either memory can serve as the frame buffer). Software supplied with this reference design runs on the Nios II embedded processor to place an image in the frame buffer memory and invokes the DB9000AVLN core to drive the LCD panel.

Using the Intel® Quartus® Design Software, you can instantiate the TFT LCD Controller reference design in a Cyclone®, Cyclone® II, or Cyclone® III FPGA development kit. See the Demonstrated Intel® Technology section for a complete list of supported Intel® FPGA development kits.

You can connect your LCD panel to the Intel FPGA development kit with the fabrication of an appropriate cable. Please contact Digital Blocks for more details.

tft lcd frame buffer in stock

This library implements a SPI driver for the ILI9341 screen controller providing the ability to display memory framebuffers onto the screen very efficiently.

Differential redraws. The driver compares the framebuffer to be uploaded with the previous one and uploads only the pixels that differ. It does so in a smart way to minimize SPI transactions. Uploading only parts of the screen makes it possible to achieve very high frame rates even with low SPI speeds.

Asynchronous updates via DMA. Upload can be performed directly or asynchronously using DMA so the MCU is free to do other tasks - like generating the next frame - during updates.

adjustable framerate. The screen refresh rate can be adjusted between 40hz and 130Hz and a fixed framerate can be set within the driver. Uploads are timed to meet the requested framerate.

Multiple buffering methods. Support direct upload and double buffering. Partial updates of the screen, with direct or deferred redraw, are also available.

(2) The library"s sole purpose is to perform framebuffer upload from memory to the screen. It does not provide any drawing primitive. You must use another canvas library to draw directly onto the memory framebuffer. To do so, you may use my TGX library which provides optimized drawing primitives for 2D and 3D graphics.

The library can work with any SPI bus. Multiples instances of the driver can manage multiple displays on different SPI buses. A significant speedup is possible when the DC pin from the ILI9341 screen is connected to a hardware CS (chip select) capable pin on the Teensy... Yes, this requirement may seems weird at first ! In that case, the library will use the SPI FIFO and DMA to their full capabilities which increases the framerate (around 35% faster) while reducing CPU usage (by around 20%).

The above buffer has been placed in the upper 512K (dmamem) portion of the memory to preserve the RAM in the faster lower portion (dtcm). Buffers can be placed anywhere in RAM (even in EXTMEM if external ram is present but there will be a speed penalty in that case).

Remark. Not using an internal framebuffer is possible but it will disable asynchronous and differential updates, thus removing most of the library benefit... ADVICE: always use double buffering !

When the library is working in double buffering mode, it can take advantage of the fact that the last internal buffer uploaded to the screen mirrors the screen content. Therefore, when a new framebuffer is to be uploaded, the library can quickly check which pixels have changed and only upload those. This provides a huge speed bump when only a fraction of pixels changes at each frame (which is common when displaying a user interface for instance). The library is said to use differential updates in that case. When performing differential updates, the library first creates a diff log of all the changes between the new framebuffer and the previous one. Once this is accomplished, it can overwrite the internal frame buffer containing the old frame with the new one and, when an update is needed, just read the diff to select the pixels that must be pushed onto the screen. Updates can be carried away asynchronously while the user code draws the next frame.

The template parameter above specifies the size (in bytes) of the buffer. It should range from 1K to 10K depending on the kind of content displayed. The method diff1.printStats() can be used to check the diff buffer memory consumption at runtime to help choose its correct size.

Remark. You can set either 0, 1 or 2 diff buffers. Not providing any diff buffer will disable differential updates. On the other hand, providing 2 diff buffers allows the driver to compute the new diff while the previous one is currently in use for an upload and thus provides a nice speed bump. ADVICE: always use two diff buffers !.

The constructor of the main ILI9341Driver object tft does not initialize anything. We must do that when ready by calling the ubiquitous arduino begin() method (usually within setup()) like so:

This method returns true if the screen was correctly initialized. Note that there is no corresponding end() method so begin() should normally be called only once (but it can still be called again to issue a hard reset). The SPI_WRITE_SPEED and SPI_READ_SPEED parameters can be omitted so default speeds for write/read SPI will be used. The SPI read speed does not really matter and should not be changed. On the other hand, the maximum possible framerate is proportional to the SPI write speed so it should be set as high as possible while still keeping a stable connexion. With short wires, many displays will easily accept speeds upward of 60Mhz...

There are 4 possible orientations for the display (matching, of course, to the four physical orientations). Each one is obtained from the previous one by rotating the screen 90 degrees clockwise. Orientation 0 and 2 are in portrait mode 240x320 whereas orientation 1 and 3 are in landscape mode 320x240. In all cases, the framebuffer layout is in row-major format: if the screen has size LX x LY, then

The "natural" orientation is orientation=0 for which the pixels in the framebuffer are ordered the same way that they are refreshed on the screen. This orientation will give the best possible upload rate and should be favored if possible.

The method can be called again to change the buffering mode on the fly. Calling this method without a parameter removes the current internal framebuffer (and the drivers switches to the inefficient direct upload mode).

Note that, without an internal framebuffer, differential updates cannot be performed so any registered diff buffers will be ignored (until an internal framebuffer is set). Whenever an internal framebuffer and at least 1 diff buffer are registered, differential updates are automatically enabled. As mentioned before: always favor 2 diffs buffers instead of 1 !

The framerate on the other hand is the number of times the screen content is actually updated by the driver every second. When pixel upload and pixel refresh are not synchronized, we end up with the screen displaying part of the old and the new frame simultaneously which create a visual defect called screen tearing.

In order to prevent this, the driver keeps track of the refresh times and tries to upload pixels trailing behind the scanline. However, if the upload rate is much slower than the refresh rate, then the scanline will still eventually catch up with the pixels being uploaded and screen tearing will occur. In order to get prevent visual artifact and insure a stable framerate, the following two conditions should be met:

The first condition depends heavily on the SPI speed. For example, with SPI set at 60Mhz, it is possible to upload up to 45 full frames per second. Being cautious, we can set a refresh rate at 80Hz and a framerate at 40Hz = (80/2) to obtain tear free frames on the screen. However, this computation is a worst case scenario: for most usage, differential updates boost the upload speed tremendously so it is often possible to get "tear free" display at 60Hz framerate (and 120Hz refresh rate) with only 20Mhz SPI speed !

Now, we must tell the driver the actual framerate/vsync method that we want. This is done with the tft.setVsyncSpacing() method. It takes as input a vsync_spacing parameter (what a surprise!)  which has the following meaning:

vsync_spacing = -1. Do not synchronize display updates with screen refreshes (no vsync).  Each new frame is drawn immediately onto the screen or saved into the internal framebuffer to be drawn asap if there is already an update in progress. If the internal framebuffer is in use, the frame is simply dropped...

vsync_spacing = 0. Do not synchronize display updates with screen refreshes (no vsync). Each new frame is drawn immediately onto the screen or saved into the internal framebuffer to be drawn asap if there is already an update in progress. If the internal framebuffer is in use, the method waits for a buffer to become available before returning (same as above but no frame is ever dropped).

vsync_spacing = N > 0. Synchronize uploads with screen refreshes to mitigate screen tearing. Perform upload every N screen refreshes so that the actual framerate is equal to framerate=refreshrate/N (provided, of course, that frames are pushed fast enough to the driver to achieve this rate).

In practice, vsync_spacing=-1 will give the fastest apparent framerate but will usually provide very poor visual quality. Setting vsync_spacing=-0 will give slightly better results (but still with screen tearing) and still leaves the responsibility to the user of setting a stable framerate by pushing frames at regular intervals... In most cases, the best choice is to set vsync_spacing = 2 and then adjust the refresh rate so that uploads can be performed at refreshrate/2 FPS... Using vsync_spacing = 1 should be reserved for drawing very simple frames which can be uploaded very quickly onto the screen (in less than a refresh period). Using vsync_pacing >= 3 can be used to artificially reduce the framerate but I do not know of a really compelling reason to do so.

What actually happens when the method is called depends on the buffering and vsync mode but, as a general rule, the method will try to return to the caller as soon as possible. It will use its internal framebuffer (if present) to save a copy of fb and return while uploading the frame asynchronously via DMA. So, when the method returns, fb may, or not, already be displayed on the screen but, in any case, the framebuffer can be immediately reused for drawing the next frame, changing its content will not affect the display on the screen !.

The setDiffGap() method. When using differential updates, the driver tries to be smart and find a compromise between skipping unchanged pixels but also not fragmenting spi transactions too much because issuing a re-positioning commands also takes times. To adjust this behaviour, the setDiffGap() can be used to specify the number of consecutive unchanged pixels required to break a spi transaction. Typical value should range between 3 and 40. Smaller gaps can provide a speed bump but will require larger diff buffers (possibly up to 10K when using a gap of size 4). It is possible to get statistics on diff buffer memory consumption with the printStats() method. If the diff buffer overflows too often, its size should be increased.

Disabling differential update for a given frame. Differential updates are beneficial in most cases unless almost all pixels change in the frame. In this case, there will be no increase in upload speed. Yet, calculating the diff log takes around 300us to 1ms of CPU time per frame. When using two diff buffers, this computation is done during DMA transfer so it will not slow down the framerate but it can still be beneficial to skip this computation if you already know for sure that the diff will be mostly trivial. You can tell the driver to upload the full frame as is, without computing the diff, by setting the second (facultative) parameter in the update method to true:

Drawing text on the framebuffer The overlayText() method can be used to draw some text onto the framebuffer. This is useful for displaying basic informations or debugging. Similarly, the method overlayFPS() draws the current instantaneous framerate onto a given framebuffer. Both methods overlayText() and overlayFPS() are typically called just before calling update().

diff buffer and memory allocation. The library performs no memory allocation. All the memory needed (framebuffer and diff buffers) are to be provided by the user which keeps complete control over memory allocation. For diff buffers, the StaticDiffBuffer<> template class provides a convenient way to create diff buffers with statically allocated memory. However, if more control is needed, one can use the base DiffBuffer class which is similar but requires the user to provide the memory space at construction time. See the file DiffBuff.h for additional details.

Getting information, additional methods. There are several other methods that can be used to fine tune the driver performance. In particular: resync(), setDiffCompareMask, setLateFrameRatio()... Details about these methods (and more) can be found in the header file ILI9341Driver.h. Each method has a detailed docstring above its declaration explaining its purpose.

Last but not least: drawing things on the frame buffer. The library itself provides not drawing primitive. It simply pushes/mirror a memory frame buffer onto the screen. You can draw on the framebuffer directly "by hand" or use any library you wish to do so... If you want a lightweight, fast, full featured 2D and 3D graphics library optimized for microcontrollers, you should check out my tgx library