Another way to potentially speed up the SPI transfers is to use one of the async
versions of the spi_transceive functions like: spi_transceive_cb
For example I added into the ST77xx library a function:
static void spi_fillrect_callback (const struct device *dev, int result, void *data) {
UNUSED(dev);
UNUSED(result);
*((volatile bool *)data) = true;
}
void ST77XX_zephyr::fillRect_async(int16_t x, int16_t y, int16_t w, int16_t h,
uint16_t color) {
beginSPITransaction();
setAddr(x, y, x + w - 1, y + h - 1);
writecommand_cont(ST77XX_RAMWR);
setDataMode();
volatile bool async_cb_called = false;
uint32_t count_pixels = w * h;
uint16_t array_fill_count = min(count_pixels, sizeof(s_row_buff)/sizeof(s_row_buff[0]));
struct spi_buf tx_buf = { .buf = (void*)s_row_buff, .len = (size_t)(array_fill_count * 2 )};
const struct spi_buf_set tx_buf_set = { .buffers = &tx_buf, .count = 1 };
for (uint16_t i = 0; i < array_fill_count; i++) s_row_buff[i] = color;
while (count_pixels) {
async_cb_called = false;
spi_transceive_cb(_spi_dev, &_config16, &tx_buf_set, nullptr, &spi_fillrect_callback, (void*)&async_cb_called);
while (!async_cb_called) {}
count_pixels -= array_fill_count;
if (count_pixels < array_fill_count) {
array_fill_count = count_pixels;
tx_buf.len = (size_t)(array_fill_count * 2 );
}
}
endSPITransaction();
}
And hacked it into the test app:
Serial.print("fillRect_async: ");
delay(250);
em = 0;
tft.fillRect_async(0, 0, tft.width(), tft.height(), ST77XX_BLACK);
tft.fillRect_async(0, 0, tft.width(), tft.height(), ST77XX_BLUE);
tft.fillRect_async(0, 0, tft.width(), tft.height(), ST77XX_GREEN);
tft.fillRect_async(0, 0, tft.width(), tft.height(), ST77XX_RED);
tft.fillRect_async(0, 0, tft.width(), tft.height(), ST77XX_YELLOW);
tft.fillRect_async(0, 0, tft.width(), tft.height(), ST77XX_WHITE);
tft.fillRect_async(0, 0, tft.width(), tft.height(), ST77XX_ORANGE);
dt = em;
Serial.print(dt);
Serial.print(" ");
em = 0;
tft.writeRect_SPI_transfer((tft.width() - IMAGE_WIDTH) / 2, (tft.height() - IMAGE_HEIGHT) / 2, IMAGE_WIDTH, IMAGE_HEIGHT, CopperAnnie);
dt = em;
Serial.println(dt);
So the code is more or less identical to the tft.fillRect() code except I use the
different call with callback where I simply set a flag ...
Test run timings:
TFT Library: 4195 66
fillRect_async: 3669 335
fillRect_SPI_transfer: 18770 336
fillRect_SPI_transfer16: 10245 184
fillRect_SPI_transfer_buf: 5648 102
fillRect_SPI_transfer_txbuf: 5603 32
Note the Aync is using the slow SPI transfer version for the writeRect.
But the fillRects is faster by about 13%
Which you can see in the SPI clock timing:
versus
Probably can speed up the fill by using multiple copies of the tx_buf
per call..
Again trying things out

