Hallo Forum,
ich hacke gerade ein bisschen an der TFT Lib vom Arduino, weil das Laden
eines 24 Bit BMP mit 160x128 ca. 3s dauert.
Anyway, folgender Fehler ist mir vollkommen unklar. Von C++ hab ich
keine Ahnung, ich mach nur C&P ;-)
In file included from C:\Programme\Arduino\libraries\TFT\src/TFT.h:6:0,
from TFTBitmapLogo.ino:25:
C:\Programme\Arduino\libraries\TFT\src/utility/Adafruit_GFX.h: In member
function 'void Adafruit_GFX::image(PImage&, uint16_t, uint16_t)':
C:\Programme\Arduino\libraries\TFT\src/utility/Adafruit_GFX.h:297:37:
error: 'setAddrWindow' was not declared in this scope
setAddrWindow(x, y, x+w-1, y+h-1);
^
Fehler beim Kompilieren.
Siehe Anhang.
Meine andere, selbstgestrickte Funktion
void Adafruit_ST7735::drawFastHblock(uint8_t *data, uint16_t cnt) {
funktioniert anscheinend. Zumindest erkennt sie der Compiler.
Naja, wo kommt denn "setAddrWindow" her? Das ist eine Memberfunktion der
Klasse Adafruit_ST7735, die von Adafruit_GFX abgeleitet ist.
Woher aber soll die Basisklasse von dieser Funktion wissen?
@ Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
>Naja, wo kommt denn "setAddrWindow" her? Das ist eine Memberfunktion der>Klasse Adafruit_ST7735, die von Adafruit_GFX abgeleitet ist.
So in etwa.
>Woher aber soll die Basisklasse von dieser Funktion wissen?
Na ich dacht mit dem Eintrag
drawFastHblock(uint8_t *data, uint16_t cnt),
in Adafruit_ST7735.h
Siehe unten.
OK, falsch gedacht. Wo muss die Deklaration noch rein (jaja, aber
wirklich, ich habe KEINE Ahnung von C++, hab nur mal vor Jahren ein C++
Buch durchgeblättert, ich weiß, C++ Buch kaufen und durcharbeiten).
So liebe Leute, hier mal mein Ergebnis. Wie gesagt, ich spiel im Moment
mit dem Arduino TFT rum, die Lib kann BMP Bilder direkt von SD-Karte auf
den TFT kopieren, allerdings ist das etwas langsam. Darum hab ich die
Funktionen etwas aufgebohrt, jetzt werden auch direkt 16 Bit BMPs
gelesen, was schon 7mal so schnell ist, ausserdem kann man Bilder in den
Flash legen und von dort direkt anzeigen, was nochmal ca. doppelt so
schnell ist!
1
Datei (B x H x Bits) Ladezeit / ms
2
48x48x24 351
3
1260x128x24 2930
4
48x48x16 47
5
160x128x16 414
6
48x48x16 (Flash) 19
7
80x128x16 (Flash) 84
Das kann sich schon mal sehen lassen.
Es gibt dabei folgende Begrenzungen.
1.) Ein einzelnes Bild im Flash darf max. 32767 Bytes groß sein, denn
hier greift leider die maximale Größe eines einzelnen char[] Arrays.
D.h. man kann nicht ganz die vollen 160x128 in ein Bild packen. Wenn man
das will, muss man es zweiteilen.
2.) Die Gesamtanzahl an Bilddaten darf 64kB nicht übersteigen, auch
nicht auf dem MEGA256, weil auch hier wieder die Grenze der Pointer im
avr gcc mit 64 kB greift. Ausserdem scheint das Programm gar nicht erst
loszulaufen, wenn deutlich mehr als 64kB Flashgröße erzeugt werden (Bug
im avr gcc, wenn der Einsprung vom Resetvektor >64kB?, Problem im
Bootloader?)
Auf dem DUE mit dem ARM sollten diese Begrenzungen nicht greifen. Kann
ich mangels Hardware aber nicht testen.
Beim Laden von Bildern vom Flash gibt es keine Größenbegrenzung.
Wenn man ein Bild in den Flash legen will, muss man
-das Bild mit einem Grafikprogramm wie GIMP o.ä. als 16 Bit BMP
speichern, wobei es als Top-Down gespeichert werden muss!
- mit dem Tool bin2c in C-Quelltext umwandeln und per include einfügen.
auf der Kommandozeile z.B. so
bin2c bild.bmp >bild.c
- die Kopfzeile muss man manuell anpassen, siehe Beispiel.
- in sketch mittels der neuen Methode TFTscreen.loadImageFlash()
"laden", dabei wird der Header dekodiert.
- Die Anzeige auf dem TFT erfolgt mit der bekannten Methode
TFTscreen.image(), welche erweitert wurde.
Das Archiv TFT.zip muss in C:\Programme\Arduino\libraries, es enthält
die erweiterten Methoden für den TFT
Das Archiv TFTBitmapLogo.zip enthält das sketch und die includes für die
Bilder sowie das tool. Im sketch muss man die Pfade der Bilder anpassen,
irgendwie mag Arduino keine relativen Pfade im Projektverzeichnis, oder?
Ach ja, das Pinout für den TFT/SD-Shield hab ich passend für meinen
Lochrasterausbau gewählt, kann man aber leicht mit den #defines am
Anfang ändern, ist glaube ich selbsterklärend.
Viel Spaß damit
Falk
Falk Brunner schrieb:> Ein einzelnes Bild im Flash darf max. 32767 Bytes groß sein, denn hier> greift leider die maximale Größe eines einzelnen char[] Arrays.
Wieso sollte es da eine Begrenzung geben? Könnte es sein, daß Du einen
ungünstigen Datentyp als Index zum Arrayzugriff verwendest?
@ Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
>> Ein einzelnes Bild im Flash darf max. 32767 Bytes groß sein, denn hier>> greift leider die maximale Größe eines einzelnen char[] Arrays.>Wieso sollte es da eine Begrenzung geben?
Weil dass der gcc auspuckt.
1
In file included from TFTBitmapLogo.ino:28:0:
2
D:\Projekte\Arduino\TFT\TFTBitmapLogo\a\che.c:1:12: error: size of variable 'che' is too large
3
const char che[] PROGMEM = {
Das Array ist ~40kB.
http://www.avrfreaks.net/forum/sizet> Könnte es sein, daß Du einen>ungünstigen Datentyp als Index zum Arrayzugriff verwendest?
Nö, er meckert über die Definition. Da gibt es noch dar keinen Index.
Ein paar Links zum Thema.
http://www.avrfreaks.net/forum/maximum-size-progmem-arrayhttp://www.avrfreaks.net/forum/sizethttps://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Flash_mit_PROGMEM_und_pgm_read
Bisschen runter, Variablenzugiff > 64kB. (ich kann keinen direkten Link
erzeugen, doofe Formatierung).
Was am Ende zu der Aussage führt, dass der ArduinoMEGA256 mit seinem
großen Speicher nutzlos ist, denn der avr gcc kann damit nicht direkt
umgehen. Ein typischer Aduinouser kann und will nicht mit den Makros und
den Linkeroptionen rumeiern, ich auch nur bedingt. Also Leute, kauft
euch besser einen Arduino DUE oder andere ARMs, die können ihren
Speicher ohne Handstände voll ausnutzen.
Der einzige Vorteil des MEGA256 sind mehr Pins und IO Module (UARTs,
SPI, Timer, PWM, etc).
Falk Brunner schrieb:> Bisschen runter, Variablenzugiff > 64kB.
da steht eigentlich RAM>64K und flash>128K
und bei dir sind es 40K im PROGMEM, muesste also so und so passen,
aber natürlich glaube ich Dir dass die Meldung kommt
Viel weiss ich auch nicht darüber, aber mir würde spontan die Wahl des
Memory-Modells als Option des AVR-GCC einfallen. Wahrscheinlich muss man
irgendwo "large" angeben.
chris_ schrieb:> ich es richtig> verstehe, gibt es beim AVR-GCC eine Limitierung auf 32k :> http://www.avrfreaks.net/forum/maximum-size-progmem-array
Die Diskussion gab es doch hier auch schon mal. Der Index ist halt per
Definition ein (signed) int, und der ist beim avr-gcc 16 bit breit. Da
ist bei 32k Arrayelementen Schluss.
Oliver
frischling schrieb:> Ich dachte es gäbe eine "logische" Erklärung.> Irgend einen Hintergrund technischer Natur.
Wie Vieles: weil's schon immer so war und jetzt kann's keiner mehr
ändern.
Die Definition erlaubt aber auch negative Indizes (und Compiler können
damit umgehen, obwohl's keiner benutzt). Mit
1
char*p,*arr;
2
inti;
3
4
p=malloc(64*1024L);
5
arr=p+32*1024L;
6
7
for(i=-32*1024;i<32*1024-1;i++)
8
arr[i]='A';
(mag sein, daß da noch ein "um eins daneben" Fehler drinsteckt, hab' ich
jetzt aus der Hüfte geschossen) kannst Du deswegen auch mit 16-Bit
signed ints 64k Arrays beackern.
frischling schrieb:> Naive gefragt, warum signed ?>> Zur Adressierung braucht es doch keine negativen Zahlen ?
Pointer-Arithmetik erlaubt die Bildung der Differenz der Adressen zweier
Elemente eines Arrays. Da diese Differenz auch negativ sein kann, wird
ein vorzeichenbehafteter Wert benötigt.
Beispiel:
Ich will in einem String die Zahl an Zeichen vom ersten e bis zum ersten
a ermitteln:
1
constchar*text="Hallo Welt";
2
3
constchar*e=strchr(text,'e');
4
constchar*a=strchr(text,'a');
5
intdiff=a-e;
Da das a vor dem e liegt, ist das Ergebnis hier negativ.