Guten Abend zusammen,
ich bin gerade dabei eine kleine Lib zu basteln und möchte dafür eine
Fonttabelle auf meinem Mega1284 speichern.
Dieser hat 16kB SRAM und 128kB Flash.
Leider scheitern meine Versuche die Arrays auszulagern. PROGMEM
ignoriert der Compiler (AVR Studio 7) vollkommen, bei EEMEM scheint er
einen Teil auszulagern weil beim Compilieren der EEPROM mit 20% mit
auftaucht. Allerdings ist der SRAM noch immer bei 115%. Lasse ich EEMEM
weg steigt der SRAM auf ca. 117%.
Der Code liegt im Anhang, wäre super wenn mir jemand einen Tip geben
könnte was ich falsch mache.
Vielen Dank!!
Gruß
Matthias
Stefan U. schrieb:> Progem ist die Lösung. Wie hast du es denn versucht?
Steht doch oben: Mit PROGMEM.
Es steht auch schon dort, dass sein "Grafik-RAM" das Problem ist und
nicht die Fonts.
> Es steht auch schon dort, dass sein "Grafik-RAM" das Problem ist und> nicht die Fonts.
Sicher? Weil wenn ich die font.h auskommentiere habe ich keine
Platzprobleme.
Matthias M. schrieb:> Weil wenn ich die font.h auskommentiere habe ich keine> Platzprobleme.
das zeigt aber auch das nächste Problem. Der Array sollte nicht in einer
Header Datei stehen. Das macht man in eine c Datei.
Auch wenn das Display vielleicht sehr preiswert war, das ist nicht
wirklich eine gute Wahl für die kleinen 8-Bit AVR.
Vor allem nicht mit Bild-Puffer.
Was anderes als SPI-Transfers wird der quasi nicht mehr machen und
dennoch nur auf ein paar Bilder pro Sekunde komme.
Mit einem FT81x basiertem TFT hat man da erheblich mehr Freude, etwa dem
RVT70UQFNWC00 von Riverdi.
Oder wenn es billiger sein soll sowas wie das FT811CB-HY50HD von HAOYU
(hotmcu.com).
Auch wenn 800x480 in 5" für Bedien-Oberflächen etwas dumm sind und
selbst 7" eigentlich noch zu klein für die Auflösung sind.
Naja, hauptsache große Zahlen fürs Marketing Geblubber, sieben RGB-Pixel
pro Millimeter sind ja viel zu wenig und so, zwar Briefmarke aber
Full-HD bitte...
Beitrag "FT800 / FT810 Library"
Die FT8xx haben auch gleich Zeichensätze mit eingebaut.
Der Witz an den Dingern ist, dass die quasi eine Grafik-Karte für
MikroController sind, die nehmen dem Controller so richtig viel ab.
Statt nen Haufen Pixel für einen Button hinzuschicken den die Grafik-Lib
auch noch ausrechnen muss schickt man dem nen Satz Daten über den SPI
für Kommandos:
Das sind 3 Bytes Adresse, plus 16 Bytes Kommando plus 8 Bytes für den
Text (muss durch vier teilbar sein) -> 27 SPI Transfers für das
ft800_cmd_button() da oben.
Die Parameter dabei sind x-pos, y-pos, x-size, y-size, font-nummer,
options.
In der Variable "button" steht drin, ob der Button flach oder in 3D
gezeichnet werden soll und das mache ich abhängig davon, ob der Button
als gedrückt erkannt wurde oder nicht.
Um den Touch kümmert sich der FT8xx selber, man weist einem einzelnen
Objekt oder auch ganzen Gruppen von Objekten ein TAG zu.
Dann liest man einfach das Register dazu aus.
Touch-Koordinaten berechnen und selber ausrechnen, was auf dem
Bildschirm gerade getroffen wurde wird komplett überflüssig.
Ich fahre die Dinger normalerweise mit 40 Bildern pro Sekunde, einfach
weil es nichts kostet da 500+ Bytes alle 25ms hin zu schicken.
Das könnte man noch optimieren so das nur eine neue Display-Liste
geschickt wird wenn auch Änderungen sind, dann müsste man aber auch
aufpassen, dass das nicht häufiger als etwa 60 Bilder pro Sekunde wird.
Matthias M. schrieb:> Es liegt am Grafik-Ram. Der ist einfach zu groß... Mist.
Das ist kein Mist, das ist auch kein Problem, da Dein Display sein
Grafik-RAM in der benötigten Größe 'on board' hat.
Ein Grafik-RAM benötigt man z.B. bei LED-Matrix-Displays (Laufschrift,
Displays an Häuser-Fassaden, ...).
Was machst Du z.B. bei 320x240 Pixel oder mehr in RGB?
Hier mal ein Beispiel: LCD_fillScreen, LCD_fillRect, LCD_DrawPixel,
LCD_setViewport usw. schreiben direkt in das Display. Hier ist das zwar
ein LCD-Controller, aber bei Deinem OLED müsste das so ähnlich gehen.
https://github.com/TorstenC/A137_TouchTFT_320x240/tree/master/Mikrocontroller/Atmel%20Studio/TimeTimer
Zum FT800: Brauchst Du einen Touch-Screen oder animierte Grafiken?
Also erstmals Danke für eure zahlreichen Antworten! Danke auch an Rudolf
bezüglich der FT800 Controller. Ich kenen diese, hab ich auf der
Embedded World gesehen und ein Bekannter verwendet diese beruflich.
Für meinen Zweck war das aber einfach zu oversized und teuer. Bin da
aber auch etwas blauäugig ran gegangen und dachte mir, die paar Zeichen
wirst ja noch aufs Display bringen ;-)
Torsten C. schrieb:> aber bei Deinem OLED müsste das so ähnlich gehen.
Hmm... also bei Kreisen und Rechtecken bin ich bei dir, das funktioniert
auch schon. Dort gibt ich dem Controller einfach den CMD für Rechteck,
sag ob ausgefüllt oder nicht, Start- Ende- Koordinaten und auf dem
Display erscheint ein Rechteck.
Aber bei Texten?!
Torsten C. schrieb:> Zum FT800: Brauchst Du einen Touch-Screen oder animierte Grafiken?
Nein, weder Farbe, noch Touch, noch Animationen...
Ein paar Linien und Texte sind für mich vollkommen ausreichend.
Matthias M. schrieb:> Hmm... also bei Kreisen und Rechtecken bin ich bei dir, …> Aber bei Texten?!
Ich verstehe, dass man dazu unterschieldiche Meinungen haben kann. Meine
Erfahrung war: Auch Texte mit Anti-Aliasing waren beim "TimeTimer"
(s.o.) auf einem ATMega328p kein Problem: LCD_DrawGlyph, LCD_DrawChar
und LCD_DrawSpacer.
Torsten C. schrieb:> Auch Texte mit Anti-Aliasing waren beim "TimeTimer"> (s.o.) auf einem ATMega328p
Aber du hast das in C++ geschrieben, oder? Oder kann man in C Funktionen
überladen?
So ganz verstehe ich deinen Code leider nicht.
Mit LCD_DrawGlyph() pickst du dir ein Zeichen aus deiner Fonts Tabelle
(die im Flash liegt) heraus und schreibst dieses über LCD_DrawPixel() in
das RAM vom Display, oder?
@All: wie bringe ich denn die von mir gepostete Lib aus dem 1. Post dazu
den Text auf das Display zu packen? Ohne den RAM im µC vorzuhalten?
Matthias M. schrieb:> Aber du hast das in C++ geschrieben, oder? Oder kann man in C Funktionen> überladen?
Es wird aber nur Überladung genutzt und die Typ-Sicherheit war recht
angenem. Weder Klassen noch new(). Die Code-Schnippsel sind also mit
wenigen Änderungen direkt in C nutzbar.
Das Beispiel funktioniert zwar (den TimeTimer hatte mein Sohn eine Zeit
lang in der Schule benutzt), das Beispiel ist aber nur als Vorlage und
nicht zur direkten unveränderten Übernahme in ein neues Projekt
geeignet. Die Font-Dateien hatte ich damals mit einem VisualStudio .NET
Programm für die benötigten Glyphen erzeugt.
> So ganz verstehe ich deinen Code leider nicht.
Frag ruhig nach, wenn Du magst, ich ergänze gern entsprechende
Kommentare.
Aber das Beispiel soll keine fertige universelle Lib sein, siehe auch
"// TODO:" im Quelltext.
> Mit LCD_DrawGlyph() pickst du dir ein Zeichen aus deiner Fonts Tabelle> (die im Flash liegt) heraus und schreibst dieses über LCD_DrawPixel() in> das RAM vom Display, oder?
Genau:
https://github.com/TorstenC/A137_TouchTFT_320x240/blob/master/Mikrocontroller/Atmel%20Studio/TimeTimer/Fonts.cpp#L115
Vorher wird ein Viewport gesetzt, weil der Display-Controller dann
automatisch nach einem DrawPixel in die nächste Spalte springt, wenn die
Spalte davor voll ist. Ob Dein OLED-Controller sowas kann, steht im
Datenblatt.
PS: Schrift mit Kantenglättung auf Hintergrund-Grafik geht so natürich
nicht, dann wären wir wieder beim Grafik-RAM. Aber 'einfarbig' mit
Kantenglättung auf 'einfarbig' könnte man so auch umsetzen.
PPS: Das hier ist eine Grafik und nicht mit dem o.g. Code erzeugt:
https://www.mikrocontroller.net/attachment/207191/DSC_6548.jpg
Mit Farbverlauf im Hintergrund und Schatten-Effekt an der Schrift. Da
wollte ich mal hin, aber das war mir aus dem o.g. Grund zu aufwendig.
Für Schatten könnte man machen statt:
// (0x1 = Hintrergrund .. 0xE = Vordergrund)
den Bereich halbieren:
// (0x1 = Hintrergrund .. 0x8 = Vordergrund)
// (0x9 = Hintrergrund .. 0xE = Schatten)
Siehe:
https://github.com/TorstenC/A137_TouchTFT_320x240/blob/master/Mikrocontroller/Atmel%20Studio/TimeTimer/Fonts.cpp#L65
Leute ich brauch eure Hilfe... komm einfach nicht weiter mit der
Textausgabe.
Display füllen, Linien und Rechtecke in verschiedenen Graustufen ist
alles schon möglich und läuft.
Aber wie bringe ich ein Zeichen aus meinem Fonts Array auf das Display??
mein Array sieht so aus:
1
const uint8_t PROGMEM F4x6[95][3] = {
2
{0x00,0x00,0x00}, //??
3
{0x44,0x40,0x40}, //!
4
{0xAA,0x00,0x00}, //"
5
{0xAE,0xAE,0xA0}, //#
6
{0x6C,0xE6,0xC0}, //$
7
{0xA2,0x48,0xA0}, //%
8
{0x4A,0x4A,0xE0}, //&
9
{0x44,0x00,0x00}, //'
10
{0x48,0x88,0x40}, //(
11
{0x42,0x22,0x40}, //)
12
{0x04,0xA4,0x00}, //*
13
{0x04,0xE4,0x00}, //+
14
{0x00,0x04,0xC0}, //,
15
{0x00,0xE0,0x00}, //-
16
{0x00,0x00,0x40}, //.
17
{0x24,0x44,0x80}, //
18
{0xEA,0xAA,0xE0}, //0
19
{0x44,0x44,0x40}, //1
20
{0xE2,0xE8,0xE0}, //2
21
{0xE2,0xE2,0xE0}, //3
22
{0xAA,0xE2,0x20}, //4
23
{0xE8,0xE2,0xE0}, //5
24
{0xE8,0xEA,0xE0}, //6
25
{0xE2,0x22,0x20}, //7
26
{0xEA,0xEA,0xE0}, //8
27
{0xEA,0xE2,0xE0}, //9
28
{0x04,0x04,0x00}, //:
29
{0x04,0x04,0xC0}, //;
30
{0x24,0x84,0x20}, //<
31
{0x0E,0x0E,0x00}, //
32
{0x84,0x24,0x80}, //>
33
{0x4A,0x24,0x40}, //?
34
{0xEA,0xEC,0xE0}, //@
35
{0x4A,0xAE,0xA0}, //A
36
{0xCA,0xCA,0xC0}, //B
37
{0x68,0x88,0x60}, //C
38
{0xCA,0xAA,0xC0}, //D
39
{0xE8,0xE8,0xE0}, //E
40
{0xE8,0xE8,0x80}, //F
41
{0xE8,0xAA,0xE0}, //G
42
{0xAA,0xEA,0xA0}, //H
43
{0xE4,0x44,0xE0}, //I
44
{0xE4,0x44,0xC0}, //J
45
{0xAC,0x8C,0xA0}, //K
46
{0x88,0x88,0xE0}, //L
47
{0xAE,0xAA,0xA0}, //M
48
{0xAE,0xEE,0xA0}, //N
49
{0x4A,0xAA,0x40}, //O
50
{0xEA,0xE8,0x80}, //P
51
{0x4A,0xAE,0x60}, //Q
52
{0xEA,0xEC,0xA0}, //R
53
{0x68,0x42,0xC0}, //S
54
{0xE4,0x44,0x40}, //T
55
{0xAA,0xAA,0xE0}, //U
56
{0xAA,0xAA,0x40}, //V
57
{0xAE,0xEE,0x40}, //W
58
{0xAA,0x4A,0xA0}, //X
59
{0xAA,0xE4,0x40}, //Y
60
{0xE2,0x48,0xE0}, //Z
61
{0xC8,0x88,0xC0}, //[
62
{0x84,0x44,0x20}, /*\*/
63
{0x62,0x22,0x60}, //]
64
{0x4A,0x00,0x00}, //^
65
{0x00,0x00,0xE0}, //_
66
{0x84,0x00,0x00}, //`
67
{0x04,0xAC,0x60}, //a
68
{0x88,0xEA,0xE0}, //b
69
{0x0E,0x88,0xE0}, //c
70
{0x22,0xEA,0xE0}, //d
71
{0x4A,0xE8,0x60}, //e
72
{0x64,0xE4,0xC0}, //f
73
{0x6A,0xE2,0x60}, //g
74
{0x88,0xEA,0xA0}, //h
75
{0x40,0x44,0x40}, //i
76
{0x20,0x62,0x60}, //j
77
{0x8A,0xCC,0xA0}, //k
78
{0x88,0x8A,0xC0}, //l
79
{0x00,0xEE,0xA0}, //m
80
{0x00,0xAE,0xA0}, //n
81
{0x04,0xAA,0x40}, //o
82
{0x4A,0xAC,0x80}, //p
83
{0x4A,0xA6,0x20}, //q
84
{0x8E,0xA8,0x80}, //r
85
{0x68,0xE2,0xC0}, //s
86
{0x44,0xE4,0x60}, //t
87
{0x0A,0xAE,0x60}, //u
88
{0x0A,0xAE,0x40}, //v
89
{0x0A,0xAE,0xA0}, //w
90
{0x00,0xA4,0xA0}, //x
91
{0xAA,0xA4,0x80}, //y
92
{0x0E,0x24,0xE0}, //z
93
{0x64,0x84,0x60}, //{
94
{0x44,0x44,0x40}, //|
95
{0xC4,0x24,0xC0}, //}
96
{0x02,0xE8,0x00}, //~
97
};
Das Zeichnen eines Pixels mache ich z.B. so:
1
void drawPxl()
2
{
3
unsigned char x,y;
4
writeDisp(0x15, CMD); /* set column address */
5
writeDisp(0x15, CMD); /* set column start address */
6
writeDisp(0x3f, CMD); /* set column end address */
7
writeDisp(0x75, CMD); /* set row address */
8
writeDisp(0x15, CMD); /* set row start address */
9
writeDisp(0x3f, CMD); /* set row end address */
10
11
writeDisp(0xFF, DATA); /* write Pixel with full brightness (0x00 = black) */
12
13
}
Das sieht dann so aus wie auf dem Bild im Anhang. Allerdings zeichnet er
auf der horizontalen immer zwei Pixel... finde ich auch noch etwas
"strange".
EDIT: Das mit den zwei Pixeln hab ich soeben rausgefunden:
-> writeDisp(0xFF, DATA); -> beschreibt 2 Pixels
-> writeDisp(0xF0, DATA); -> beschreibt 1 Pixel (das Linke)
-> writeDisp(0xF0, DATA); -> beschreibt 1 Pixel (das Rechte)
Sooo... nun aber, wie bringe ich es fertig dass ich z.B. folgende
Funktion drawString("Hello World") aufs Display bringe??
Die Funktion drawString() muss mir dann ja für jeden Buchstaben den
jeweiligen HexCode aus der Font Tabelle raussuchen, oder? Aber wie bring
ich die Hex Zeichen dann aufs Display?
Ich hoffe ihr könnt mir helfen :)
Danke!!
Matthias M. schrieb:> muss natürlich so heißen:
... und ich dachte immmer: jedes Pixel bekommt 16 Bit.
Wieder was dazugelernt.
Again what learned sachd der Loddar.
Ich habe hier in einer anderen Lib ein recht übersichtliches Beispiel
gefunden.
Benötige aber auch hier etwas Hilfestellung:
Hier wird ein CHAR Zeichen übergeben... angenommen wir möchten ein "r"
zeichnen würde der Aufruf doch LCD_UC1701_PRINT_ASC(r) lauten, oder?
1
void LCD_UC1701_PRINT_ASC(unsigned char wert) { // zeichnet ein ASCII
So nun wird geschaut an welcher Stelle im Array das Zeichen steht:
1
// position im Array berechnen
2
c_pos=wert-LCD_FIRST_CHAR;
Etwas umgeschrieben heißt das doch: c_pos = r-0x20 ??
Habe ich da einen Knopf im Kopf oder wie kommt das Programm dabei auf
eine vernünftige Position im Array?
Vielleicht könnt ihr mich erleuchten ;-) Danke!!
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang