8 Bit ILI9341 2.8" Display & Arduino DUE sehr langsam! (Adafruit Lib)

So nachdem ich nun endlich das 2.8" Display mit Touchscreen (ist ein Shield für den Arduino Uno) unter dem Arduino Due zum Laufen gebracht habe muss ich nun leider feststellen, dass ich kaum Geschwindigkeitsvorteile mit dem DUE habe. Er ist meist noch nicht einmal doppelt so schnell. Hätte das ca. 4-5 Fache gegenüber den Uno erwartet.
Angeschlossen ist das Display über das 8 Bit Interface. Angeblich soll das ja auch schneller sein als SPI . SPI Anschlüsse hat das Display außerdem sowieso nicht :frowning: Des Weiteren benutzt ich die “Adafruit TFTLCD-Library-master” Library welche meinen ILI9341 Displaycontroller supportet sowie die “Adafruit-GFX-Library-master” Library (siehe Anhang).
Aus einem damaligen Projekt erinnere ich mich noch, dass digitalWrite() etc. nicht gerade sehr schnell ist und man bestimmte Pin-Manipulations Libraries benutzen soll. Wenn ich das aber richtig sehe ist die Adafruit LCD Library schon für Pin-Manipulationen optimiert und legt die 8 Bit Werte direkt auf den PORTC (PIOC).
Hier in der pin_magic.h gefunden:

#else // Due w/Breakout board

    #define write8inline(d) { \
		PIO_Set(PIOC, (((d) & 0xFF)<<1)); \
		PIO_Clear(PIOC, (((~d) & 0xFF)<<1)); \
		WR_STROBE; }

    #define read8inline(result) { \
		RD_ACTIVE;   \
		delayMicroseconds(1);      \
		result = ((PIOC->PIO_PDSR & 0x1FE) >> 1); \
		RD_IDLE;}

    #define setWriteDirInline() { \
	    PIOC->PIO_MDDR |=  0x000001FE; /*PIOC->PIO_SODR |=  0x000001FE;*/ PIOC->PIO_OER |=  0x000001FE; PIOC->PIO_PER |=  0x000001FE; }

    #define setReadDirInline() { \
		pmc_enable_periph_clk( ID_PIOC ) ; \
		PIOC->PIO_PUDR |=  0x000001FE; PIOC->PIO_IFDR |=  0x000001FE; PIOC->PIO_ODR |=  0x000001FE; PIOC->PIO_PER |=  0x000001FE; }

    // When using the TFT breakout board, control pins are configurable.
    #define RD_ACTIVE	rdPort->PIO_CODR |= rdPinSet		//PIO_Clear(rdPort, rdPinSet)
    #define RD_IDLE		rdPort->PIO_SODR |= rdPinSet		//PIO_Set(rdPort, rdPinSet)	
    #define WR_ACTIVE	wrPort->PIO_CODR |= wrPinSet		//PIO_Clear(wrPort, wrPinSet)
    #define WR_IDLE		wrPort->PIO_SODR |= wrPinSet		//PIO_Set(wrPort, wrPinSet)
    #define CD_COMMAND	cdPort->PIO_CODR |= cdPinSet		//PIO_Clear(cdPort, cdPinSet)
    #define CD_DATA		cdPort->PIO_SODR |= cdPinSet		//PIO_Set(cdPort, cdPinSet)
    #define CS_ACTIVE	csPort->PIO_CODR |= csPinSet		//PIO_Clear(csPort, csPinSet)
    #define CS_IDLE		csPort->PIO_SODR |= csPinSet		//PIO_Set(csPort, csPinSet)

 #endif

Daher gehe ich jetzt davon aus das das 8-Bit Interface schon “maximal” schnell ist. Bis auf die reset() Funktion die scheinbar kaum genutzt wird benutzt scheinbar nichts mehr digitalWrite() in der LCDTFT Library. Die analogen Pins welche für LCD_RD, LCD_WR, LCD_CD,LCD_CD und LCD RST benutzt werden scheinen auch schon als Ports angesprochen zu werden wobei ich mir da nicht ganz sicher bin da ich die Funktion digitalPinToPort() noch nicht wirklich kennen.

Adafruit_TFTLCD::Adafruit_TFTLCD( //cs,cd,wr,rd,reset are currently Analog ports
  uint8_t cs, uint8_t cd, uint8_t wr, uint8_t rd, uint8_t reset) :
  Adafruit_GFX(TFTWIDTH, TFTHEIGHT) {

#ifndef USE_ADAFRUIT_SHIELD_PINOUT
  // Convert pin numbers to registers and bitmasks
  _reset     = reset;
  #ifdef __AVR__
    csPort     = portOutputRegister(digitalPinToPort(cs));
    cdPort     = portOutputRegister(digitalPinToPort(cd));
    wrPort     = portOutputRegister(digitalPinToPort(wr));
    rdPort     = portOutputRegister(digitalPinToPort(rd));
  #endif
  #if defined(__SAM3X8E__)
    csPort     = digitalPinToPort(cs);
    cdPort     = digitalPinToPort(cd);
    wrPort     = digitalPinToPort(wr);
    rdPort     = digitalPinToPort(rd);
  #endif
  csPinSet   = digitalPinToBitMask(cs);
  cdPinSet   = digitalPinToBitMask(cd);
  wrPinSet   = digitalPinToBitMask(wr);
  rdPinSet   = digitalPinToBitMask(rd);
  csPinUnset = ~csPinSet;
  cdPinUnset = ~cdPinSet;
  wrPinUnset = ~wrPinSet;
  rdPinUnset = ~rdPinSet;
  #ifdef __AVR__
    *csPort   |=  csPinSet; // Set all control bits to HIGH (idle)
    *cdPort   |=  cdPinSet; // Signals are ACTIVE LOW
    *wrPort   |=  wrPinSet;
    *rdPort   |=  rdPinSet;
  #endif
  #if defined(__SAM3X8E__)
    csPort->PIO_SODR  |=  csPinSet; // Set all control bits to HIGH (idle)
    cdPort->PIO_SODR  |=  cdPinSet; // Signals are ACTIVE LOW
    wrPort->PIO_SODR  |=  wrPinSet;
    rdPort->PIO_SODR  |=  rdPinSet;
  #endif
  pinMode(cs, OUTPUT);    // Enable outputs
  pinMode(cd, OUTPUT);
  pinMode(wr, OUTPUT);
  pinMode(rd, OUTPUT);
  if(reset) {
    digitalWrite(reset, HIGH);
    pinMode(reset, OUTPUT);
  }
#endif

  init();
}

Hier noch die Benchmarkergebnisse des UNO und DUE:

===========================
Arduino DUE Ergebnisse:
===========================
TFT size is 240x320
Found ILI9341 LCD driver
Benchmark                Time (microseconds)
Screen fill              589958
Text                     243888
Lines                    2629141
Horiz/Vert Lines         82337
Rectangles (outline)     61069
Rectangles (filled)      1803457
Circles (filled)         791613
Circles (outline)        1148910
Triangles (outline)      833864
Triangles (filled)       880018
Rounded rects (outline)  379342
Rounded rects (filled)   2132058
Done!

===========================
Arduino UNO Ergebnisse:
===========================
Using Adafruit 2.8" TFT Breakout Board Pinout
TFT size is 240x320
Found ILI9341 LCD driver
Benchmark                Time (microseconds)
Screen fill              1379560
Text                     344032
Lines                    3390180
Horiz/Vert Lines         144660
Rectangles (outline)     104264
Rectangles (filled)      3267472
Circles (filled)         1211480
Circles (outline)        1475104
Triangles (outline)      1075600
Triangles (filled)       1719024
Rounded rects (outline)  506432
Rounded rects (filled)   3795236
Done!

Also wenn ich das richtig sehe ist die Adafruit Library schon sehr für Pin-Manipulationen optimiert und scheint mir nicht die Ursache zu sein. Warum ist der Display aber trotzdem so langsam? Woran kann das liegen? Hatte jemand ähnliche Problem und eine Lösung gefunden?

Adafruit-GFX-Library-master.zip (282 KB)

TFTLCD-Library-master-ILI9341-8Bit.zip (145 KB)

Hallo,

ich habe mal getestet:
ILI9341 Test!
Display Power Mode: 0x9C
MADCTL Mode: 0x48
Pixel Format: 0x5
Image Format: 0x0
Self Diagnostic: 0xC0
Benchmark Time (microseconds)
Screen fill 1174460
Text 159720
Lines 443864
Horiz/Vert Lines 99296
Rectangles (outline) 64228
Rectangles (filled) 2397608
Circles (filled) 335328
Circles (outline) 307380
Triangles (outline) 109084
Triangles (filled) 963132
Rounded rects (outline) 138752
Rounded rects (filled) 2415200
Done!

Das alles auf einem Mega 2560.
Beipsiel und Lib usw. von

(ich hoffe man darf Links einfügen...).

Vielleicht hilft es dir weiter...

Gruß Uwe

Guten Abend Uwe
Hab’s mir soeben die Lib mal schnell angeschaut. Im Benchmark bist bei den Linien ca. 5x schneller! Nice… so etwas hätte ich eigentlich auch erwartet.
Lines 2629141 vs Lines 443864

Allerdings scheint deine Lib SPI zu nutzen was ich eben nicht nutzen kann da auf der Platine keine SPI Anschlüsse existieren. Muss mein Shield nochmal genauer überprüfen ob nicht doch iwie die LCD_RD, LCD_WR, LCD_CD,LCD_CD und LCD RST Pins auch für SPI benutzt werden können. Der verbaute SD Slot lässt sich z.B. per SPI ansprechen

Vielleicht habe ich aber etwas interessantes in meiner Adafruit Lib gefunden. Und zwar scheinen beim ILI9341 die Pixel über 32Bit Adressen angesprochen zu werden. Da aber nur ein 8 Bit Bus dafür existiert muss er um ein einziges Pixel zu adressieren die 32 Bit Adresse in 4x8 Bit Stücke aufteilen und hintereinander senden. Heißt jedes mal wenn ich einen Pixel anspreche werden 4x 8 Bit für die Adressierung hintereinander auf den 8 Bit Bus gelegt und danach nochmal 2 mal 8 Bit für die 16 Bit Farbe. Und wie ich sehe werden jedes mal zwischen den 8 Bit 10 Microsekunden pause einngelegt. Hier der Code:

Alles aus der Adafruit_TFTLCD.cpp
//aus drawPixel()
drawPixel(){ 
...
} else if ((driver == ID_9341) || (driver == ID_HX8357D)) {
    setAddrWindow(x, y, _width-1, _height-1);
    CS_ACTIVE;
    CD_COMMAND; 
    write8(0x2C);
    CD_DATA; 
    write8(color >> 8); write8(color);
  }
...
}

//die 32Bit Adresseirung des ILI9341
setAddrWindow(){
...
} else if ((driver == ID_9341) || (driver == ID_HX8357D)){
    uint32_t t;

    t = x1;
    t <<= 16;
    t |= x2;
    writeRegister32(ILI9341_COLADDRSET, t);  // HX8357D uses same registers!
    t = y1;
    t <<= 16;
    t |= y2;
    writeRegister32(ILI9341_PAGEADDRSET, t); // HX8357D uses same registers!

  }
...
}

//und die Umsetzung der 32 Bit Adressierung:
void Adafruit_TFTLCD::writeRegister32(uint8_t r, uint32_t d) {
  CS_ACTIVE;
  CD_COMMAND;
  write8(r);
  CD_DATA;
  delayMicroseconds(10);
  write8(d >> 24);
  delayMicroseconds(10);
  write8(d >> 16);
  delayMicroseconds(10);
  write8(d >> 8);
  delayMicroseconds(10);
  write8(d);
  CS_IDLE;
}

Kann es sein dass somit der 8 Bit Bus letztendlich sogar langsamer ist als eine auf 84 MHz getaktete SPI Schnittstelle???
Bei jedem Pixeldraw wird mind. 4x delayMicroseconds(10); gemacht. Heißt eine Linie mit 100 Pixel benötigt mind. 4000 Micorsec. und sicherlich noch mehr wenn die Farbe etc noch über den 8 Bit Bus gehen muss und und und…

Nochmals kurz: Freut mich dass es wohl was genutzt hat. Wie gesagt, ich habe es am MEGA weil ich viele Ports brauche.
Ich habe das Display (mit SD) so angeschlossen:
Alle Signal vom Arduino über Spannungsteiler 1:2 (1k/2k gegen Masse) angeschlossen. Direkt am Display habe ich die MISO, MOSI und SCK von SD und LCD verbunden.
Folgende Ports habe ich genommen:

D7 TFT_RST
D8 TFT_DC
D9 TFT_CS
D50 MISO SD und TFT
D51 MOSI SD und TFT
D52 CLK SD und TFT
D53 CS SD-Card-Reader

Weiter viel Erfolg…

Danke. ...interessant. Dann ist also der am SPI angeschlossenen SD-Karten Slot auch für den Display gedacht? Muss ich mal testen.
Mein Shield sieht in etwas so aus: ebay

Hab mittlerweile mal die Adafruit Lib etwas bearbeitet und die delayMicroseconds(1); auf 1 stat 10 gesetzt.

 void Adafruit_TFTLCD::writeRegister32(uint8_t r, uint32_t d) {
  CS_ACTIVE;
  CD_COMMAND;
  write8(r);
  CD_DATA;
  delayMicroseconds(1);
  write8(d >> 24);
  delayMicroseconds(1);
  write8(d >> 16);
  delayMicroseconds(1);
  write8(d >> 8);
  delayMicroseconds(1);
  write8(d);
  CS_IDLE;

}

Neues Benchmarkergebnis ist :o. bei den Lines sieht's jetzt schon mal besser aus:

Using Adafruit 2.8" TFT Breakout Board Pinout
TFT size is 240x320
Found ILI9341 LCD driver
Benchmark                Time (microseconds)
Screen fill              573118
Text                     80514
Lines                    724287
Horiz/Vert Lines         72016
Rectangles (outline)     48101
Rectangles (filled)      1743582
Circles (filled)         385162
Circles (outline)        315675
Triangles (outline)      229728
Triangles (filled)       649057
Rounded rects (outline)  128597
Rounded rects (filled)   1943626
Done!

Das ist meines, allerdings ohne Touch.

K habs SPI nochmal auf dem Uno und Due getestet. So wie es aussieht sind keine SPI Pins “verlegt” worden. Ist halt nen einfaches Shield für den Uno. An SPI hat man wohl hier nicht gedacht. Datasheets sind chinesisch oder was auch immer und das was man lesen kann deutet nicht auf eine SPI Unterstützung hin.
Hab nun nochmal meine Libs durchstöber die vom Verkäufer angegeben waren und darin gesehen, dass die ähnlich wie die Adafruit TFTLCD Lib funktionierten, nur das man dort komplett auf die delayMicroseconds(10); verzichtet hat. Habs nun auch komplett aus der writeRegister32() Funktion raus genommen.
Mehr geht dann aber wohl auch nimmer. Die drawLine bzw. drawPixel Funktion hat nun den 5-fachen speed … immerhin ca. das Niveau von deinem Mega über SPI erreicht :frowning: .

Testergebnisse:

TFT LCD test
Using Adafruit 2.8" TFT Breakout Board Pinout
TFT size is 240x320
Found ILI9341 LCD driver
Benchmark                Time (microseconds)
Screen fill              518139
Text                     57545
Lines                    471290
Horiz/Vert Lines         63505
Rectangles (outline)     41865
Rectangles (filled)      1553222
Circles (filled)         307649
Circles (outline)        205036
Triangles (outline)      149488
Triangles (filled)       560245
Rounded rects (outline)  91906
Rounded rects (filled)   1720920
Done!

Falls jetzt noch jemand ne Idee hat wie man da noch mehr Geschwindigkeit raus bekommt würde ich mich natürlich über Hinweise freuen. Wenn man den Display von oben bis unten voll mit Text schreibt sieht man halt trotzdem noch wie sich das “Textbild” von oben nach unten aufbaut.
Die momentan “gefixte” Lib hab ich mal angehängt. Fix gilt nur für den ILI9341!

TFTLCD-Library-master-ILI9341-8Bit - fixed slow drawspeed.zip (147 KB)