Hi @CamilaSouza
Thanks for pointing me to another sample. Yes it was the SPI speed that needed to be increased. However just increasing it did not work as SPI3 was already at max. Sure TFT_eSPI is a 3rd party library, so I digged a little deeper into it.
I was able to highly increase (sorry for not having a concrete number, but it was faster than the 5Hz refresh rate I set for the camera stream without any tearing for a larger area 240x160) the speed to refresh the display. These were the steps
Summary
(1) Use the SPI5 on the Spresense board (2) with DMA enabled and (3) push all pixels at once.
More detail
Recompile the arduino SDK with one change in configuration which is to activate CONFIG_LCD_ON_MAIN_BOARD.
This enables DMA on SPI5. You only need to activate it. Then the SPI transfer call from Arduino SDK automatically uses DMA.
Add the following code to your initialization of the display (yes the include is hacky as this is not exported to the Arduino SDK)
#include "/Users/jens/work/mcu_prj/prj/spresense/references/spresense-sdk/spresense/nuttx/arch/arm/src/cxd56xx/cxd56_spi.h"
#include <arch/board/board.h>
static void initDMA() {
#if defined(CONFIG_CXD56_DMAC)
DMA_HANDLE hdl;
dma_config_t conf;
hdl = cxd56_dmachannel(DISPLAY_DMA_TXCH, DISPLAY_DMA_TX_MAXSIZE);
if (hdl) {
conf.channel_cfg = DISPLAY_DMA_TXCH_CFG;
conf.dest_width = CXD56_DMAC_WIDTH8;
conf.src_width = CXD56_DMAC_WIDTH8;
cxd56_spi_dmaconfig(DISPLAY_SPI, CXD56_SPI_DMAC_CHTYPE_TX, hdl, &conf);
}
hdl = cxd56_dmachannel(DISPLAY_DMA_RXCH, DISPLAY_DMA_RX_MAXSIZE);
if (hdl) {
conf.channel_cfg = DISPLAY_DMA_RXCH_CFG;
conf.dest_width = CXD56_DMAC_WIDTH8;
conf.src_width = CXD56_DMAC_WIDTH8;
cxd56_spi_dmaconfig(DISPLAY_SPI, CXD56_SPI_DMAC_CHTYPE_RX, hdl, &conf);
}
#endif
}
Now you can set SPI speed higher because you can use SPI5 without level shifters.
It worked on the ST7789 too without level shifters. I only use MOSI and CLK on the main board. Other connections are to LTE extension board. So a 1.8V and 3.3V mix. (I assume connecting MISO which is unused would destroy the board as the display runs on 3.3V ...)
Max speed is 48.75Mbps according to the documentation. I set it to 30 Mhz, otherwise I get artifcats on the screen. If you have a good connection, maybe 40 Mhz will work (see define in board.h ILI9340_SPI_MAXFREQUENCY 40000000).
By using lvgl, I actually only draw pixels in a region directly, thus only the TFT_eSPI function pushPixels() is used. That function transferred 16 bit at a time via SPI. Modifying this function to transfer all data at once greatly increased speed again. (that means I modified TFT_eSPI so much that it is used only for initialization)
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
spi.transfer(data_in, len);
}
You need to take care of display endianess if you transfer all at once, so swap the colors before transferring them.
void swapColors(uint16_t *colors, uint32_t len) {
uint16_t *data = (uint16_t *)colors;
while (len--) {
*data = __builtin_bswap16(*data);
data++;
}
}