Description
Not sure if this is better as a discussion versus an issue.
But I have been playing with SPI like display drivers to run on zephyr and notice that at least
on the Portenta H7 and GIGA, that the speed for updating the screen is not great.
This is largely due to not being able to fully utilize the full band width of the SPI buss.
For what is worth, I am hacking up an ST77XX display driver, similar to the ones that we (mostly @mjs512 and myself) have generated for the Teensy boards. These are loosely based off of Adafruit drivers and ones that were sped up by Paul Stoffregen (PJRC).
The ST77XX driver is WIP (more like Play in Progress) up at:
https://github.com/KurtE/Arduino_GIGA-stuff/tree/main/libraries/ST77XX_zephyr
And currently have it working with ST7796 and some ST7788 displays, will be adding in the code for
ST7735 soon.
Here shows with ST7789 240x320
There are large gaps of time between outputs. I understand this with the SPI.transfer() calls as it has to wait
for the byte to be output and received and the data to return to caller. As you can see they are pretty
large gaps here:
Probably not much that can be done here. But for example when I am doing something like a fillScreen
or the like, I send a buffer to it.
Like extracted from the fillRect:
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) {
spi_transceive(_spi_dev, &_config16, &tx_buf_set, nullptr);
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 );
}
}
My init code hacks in to get a handle to the SPI device and I call out to spi_transceive to do the transfer
It preforms better
But still leaves the bus unused for something near half the time.
Note: Each of the above outputs are 16 bits.
Is there a way in zephyr to reduce the interbyte gap?
Maybe something with the config?
Currently for the _config16, I have:
memset((void *)&_config16, 0, sizeof(_config16));
_config16.frequency = _SPI_CLOCK;
_config16.operation = SPI_WORD_SET(16) | SPI_TRANSFER_MSB;
Thanks