adafruit / Adafruit-GFX-Library

Adafruit GFX graphics core Arduino library, this is the 'core' class that all our other graphics libraries derive from
https://learn.adafruit.com/adafruit-gfx-graphics-library
Other
2.36k stars 1.53k forks source link

SPI_BEGIN_TRANSACTION is slowing down transmissions on SAMD51 #400

Open fvzeppelin opened 2 years ago

fvzeppelin commented 2 years ago
  1. Setup SPITFT with 24MHz SCK (which is hard to set up, s. https://github.com/arduino/ArduinoCore-samd/issues/680. In my case, I used an SSD1331 RGB OLED.
  2. Using the current, unmodified GFX lib 1.11.3, I measure a time between consecutive 8-bit transfers of ~6us.
  3. Modification in Adafruit_SPITFT.cpp: comment out line 2068:
    inline void Adafruit_SPITFT::SPI_BEGIN_TRANSACTION(void) {
    if (connection == TFT_HARD_SPI) {
    #if defined(SPI_HAS_TRANSACTION)
    //    hwspi._spi->beginTransaction(hwspi.settings);
    #else // No transactions, configure SPI manually...
    #if defined(__AVR__) || defined(TEENSYDUINO) || defined(ARDUINO_ARCH_STM32F1)
    hwspi._spi->setClockDivider(SPI_CLOCK_DIV2);
    #elif defined(__arm__)
    hwspi._spi->setClockDivider(11);
    #elif defined(ESP8266) || defined(ESP32)
    hwspi._spi->setFrequency(hwspi._freq);
    #elif defined(RASPI) || defined(ARDUINO_ARCH_STM32F1)
    hwspi._spi->setClock(hwspi._freq);
    #endif
    hwspi._spi->setBitOrder(MSBFIRST);
    hwspi._spi->setDataMode(hwspi._mode);
    #endif // end !SPI_HAS_TRANSACTION
    }
    }

    This modification will reduce the above mentioned delay between consecutive 8-bit transfers to ~0.8us(!).

As to my understanding of the library's design I think that this behaviour is unintended and, additonally, it is really painful because it makes a huge difference in screen build-up: It's the difference between slow top-to-down build-up and an instant one.

P.S. When I had not yet tracked down things to this point, I started a question here: https://forums.adafruit.com/viewtopic.php?t=194182. Nevertheless, I think this issue is appropriate, here.

fvzeppelin commented 2 years ago

Here is the code I used now to reproduce the issue on an ItsyBitsy M4. Just provide rgb data in splash.h and you will see the difference with the line commented out as described above while PCHCTRL and BAUD are configured identically in both cases:

#define OLED_CS_PIN  A5
#define OLED_DC_PIN  A4
#define OLED_RST_PIN A3

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1331.h>
Adafruit_SSD1331 *oled;
#include "splash.h"
uint16_t OLED_Background_Color   = 0x0000;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  SPI.begin();
  oled = new Adafruit_SSD1331(&SPI, OLED_CS_PIN, OLED_DC_PIN, OLED_RST_PIN);
  oled->begin(24000000);
  sercom1.setBaudrateSPI(0);
  oled->fillScreen(OLED_Background_Color);
  oled->drawRGBBitmap(0, 0, (const uint16_t *)image_data_splash_rgb, 96, 64);
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("PCHCTRL: ");
  Serial.println(GCLK->PCHCTRL[SERCOM1_GCLK_ID_CORE].reg);
  Serial.print("BAUDREG: ");
  Serial.println(SERCOM1->SPI.BAUD.reg);
  delay(1000);
}

Actually, I do not understand this behaviour, as the mentioned line should not make a difference. Nevetheless, it does.