Hallo liebe Foren Teilnehmer,
Ich bin noch nicht richtig sattelfest in der Programmiersprache C und
wage mich derzeit an ein GLCD heran. Die meisten Grundfunktionen passen
soweit aber nun hänge ich an der Programmierung entsprechender Schriften
und möchte das Rad auch nicht neu erfinden.
Ich habe im Netz folgende Software gefunden:
http://www.eran.io/the-dot-factory-an-lcd-font-and-image-generator/
Mit dieser Software kann man beliebeige Fonts aus dem PC in C Arrays
wandeln, siehe auch Beispiel im Anhang. Soweit so gut. Nun kommt mein
Problem. Der erste Teil, die Fonts sind mir noch klar. In meinem GLCD
Code habe ich ja eine set/clear Pixel Funktion und wenn ich das Array
Character für Character lese dann setze ich eben ein Pixel wenn die BIT
Position 1 ist und wenn 0 dann eben nicht. Was ich nicht hinbekomme ist
der Umstand das die Zeichen eine variable Breite haben. Die Information
sitzt ja in...
const FONT_CHAR_INFO georgia_12ptDescriptors[] =
aber wie kann ich das jetzt alles zusammenbauen ? Ich bräuchte einen
Lösungsansatz wie ich aus dem Array nun alles zusammenbekomme so das ich
die Schrift, genauso wie im Array dargestellt, ausgeben kann.
Danke für eure Hilfe
Lieben Gruß
Felix schrieb:> Ich bräuchte einen> Lösungsansatz wie ich aus dem Array nun alles zusammenbekomme
Wenn du schon pixelweise arbeitest (ist halt langsam), dann setzt du
eben nacheinander alle Pixel eines Zeichens, und dann gehst du nach
rechts um die Breite des Zeichens plus Abstand (z.B. 1 Pixel). Und für
die nächste Zeile nach unten um die Höhe des Fonts plus Abstand (es sind
ja alle Zeichen gleich hoch). Jeweils bis das Display aufhört.
Georg
Felix schrieb:> Hallo Georg,>>>> Wenn du schon pixelweise arbeitest (ist halt langsam)> ich bin für jeden Vorschlag offen. Wie würdest du es machen ?
Mach es erstmal Pixel für Pixel!
Wenn du das verstanden hast, verstehst du auch, wie man sowas optimieren
kann.
Felix schrieb:> Der erste Teil, die Fonts sind mir noch klar. In meinem GLCD Code habe> ich ja eine set/clear Pixel Funktion und wenn ich das Array Character> für Character lese dann setze ich eben ein Pixel wenn die BIT Position> 1 ist und wenn 0 dann eben nicht.
Funktioniert das denn schon für ein einzelnes Zeichen?
In dem Descriptors-Array hast du für jedes Zeichen drinstehen, wie breit
es ist (in Pixel/Bits) und ab wo es im Bitmaps-Array anfängt. Wenn es
mehr als 8 Pixel/Bits breit ist, werden pro Zeile 2 Bytes (vermutlich
bei mehr als 16 Pixel 3 Bytes, etc) benutzt.
Das einzig verwirrende ist die Höhe: In deinem Beispiel steht in der
Info-Struct als Höhe "2", die Zeichen selbst scheinen aber 15 Zeilen
hoch zu sein. Irgendwas stimmt da nicht.
Schnell runter getippt (die struct-element-Namen hab ich mir
ausgedacht):
Felix schrieb:> aber wie kann ich das jetzt alles zusammenbauen ? Ich bräuchte einen> Lösungsansatz...
Den gibt es doch schon seit einer gefühlten Ewigkeit. Lade dir hier im
Forum die Lernbetty herunter, da findest du sowohl Fonts als auch ein
dazu passendes GDI.
Ich hab mal dein Beispiel und die von dir genannte Seite angeschaut.
Nun, man kann es ja so machen, das Prinzip ist ähnlich dem, was ich vor
etwa 7 Jahren bei der Lernbetty
Beitrag "Die Lernbetty: Die SwissBetty von Pollin als ARM-Evalboard"
gemacht habe - aber es ist sowohl Platzverschwendung als auch eine
Umständlichkeit dadurch, daß zum einen die Glyphen immer
verschwenderisch als volle Bytes gespeichert werden und zum anderen, daß
jeweils mehrere Strukturen für nur einen Font herumfliegen:
georgia_12ptBitmaps, georgia_12ptDescriptors und georgia_12ptFontInfo.
Ich hatte das damals anders gemacht: ein Font ist da ein einziger Block
von Bytes, dies aber mit einer inneren Struktur:
- Zuerst der Font-Header, der enthält
- HCap = Höhe der Capitals über der Schreiblinie
- Height = Gesamthöhe
- Ascent = Höhe über der Schreiblinie
- Descnt = Tiefe unter der schreiblinie
- Min und Max = kleinstes und größtes enthaltenes Zeichen
- dann die Char-Header, die enthalten:
- OffHi und OffLo = Offset des Glyphs im Font
- DeltaX = zu zeichnende Zeichenbreite
- DeltaY = zu zeichnende Zeichenhöhe
- dann alle Glyphs als Bitstreams, also ohne Align auf Bytegrenze.
Wie du sehen kannst, ist das Beispiel von dir so ziemlich exakt
dasselbe, bloß daß die 3 Teile Fontheader, Charheaders, Glyphs stehen da
in umgekehrter Reihenfolge und die Glyphs sind mit viel leerem Platz auf
Bytes aufgerundet.
So, die Lernbetty ist jetzt etwa 7 Jahre her und dort ist auch eine
passende Funktion dabei, die ein Zeichen im gewählten Font an beliebiger
Stelle im Display-RAM zeichnet. Wichtig dabe ist, daß diese Funktion die
tatsächliche Zeichenbreite zurückliefert, damit man Strings ausgeben
kann, auch wenn der Font anders als Courier eben keine festen
Zeichenbreiten hat.
Siehe auch:
https://www.mikrocontroller.net/attachment/291357/Fonts_machen.ziphttps://www.mikrocontroller.net/attachment/301321/Fonts-machen-2.zipGeorg schrieb:> Wenn du schon pixelweise arbeitest (ist halt langsam),...
Das ist hier ohne Alternative, denn letztendlich muß man immer
pixelweise arbeiten, denn die Pixel müssen ja auf dem Display zu sehen
sein.
Eine Alternative in Form von Adobe- oder TrueType-Fonts kann man auf
einem µC vergessen. Das wäre sowohl von der CPU als auch von den hier
üblichen GLCD's nicht wirklich machbar.
W.S.
> ... Platzverschwendung ...> ... langsam ...
Erstmal überhaupt was hinbekommen, optimieren kann man später.
> muß man immer pixelweise arbeiten
Ich denke, Georg meinte, dass es schneller wäre, gleich mehrere Pixel in
einem Rutsch (I2C-Kommando) zu bearbeiten.
> Wichtig dabe ist, daß diese Funktion die tatsächliche Zeichenbreite> zurückliefert,
Ach so, ja, draw_string fehlte oben noch:
Es kommt auch auf den GLCD chip an, manche erlauben aneienander gereihte
PixelBytes, bzw erwarten diese sogar oder haben einen Char Buffer zum
beschreiben.
Um die optimale Vorrgehensweise zu wählen oder allgemein einen guten Tip
zu müsste man wissen welcher Controller das ist.
Es gibt so viele Varianten wie man Displays ansteuern und Fonts
vorhalten kann das es fast unmöglich ist da die Eingangsfrage mit DER
Lösung zu beantworten.
Oft liegen Fonts so vor und Displays wollen es anders rum haben, dann
ist immer Umrechnerei dazwischen nötig.
Will man Produkte in Umlauf bringen ist das Kopieren von Fonts zudem ein
rechtliches Problem, mal eben einen WindowsFont zu "klauen" kann Ärger
geben.
Je nach Rahmenbedingungen lohnt es sich das fertige Display Image
komplett im Speicher des µC zu beschreiben und dann nur die geänderten
Bereiche optimal schnell ans Display zu senden.
foobar schrieb:> Ich denke, Georg meinte, dass es schneller wäre, gleich mehrere Pixel in> einem Rutsch (I2C-Kommando) zu bearbeiten
So isses - aber bei LCDs ist sowieso in den meisten Fällen ein halbes
oder ganzes Byte zu schreiben, also auf einmal 4 oder 8 Pixel
nebeneinander. Wenn aber die Position dafür nicht mit einer
Zeichengrenze übereinstimmt wird das kompliziert. I.A. ist es am
einfachsten, die Pixel in einem RAM-Buffer zu setzen und diesen Buffer
dann byteweise an das LCD zu senden.
Im konkreten Fall sollte der TO erst mal alles pixelweise machen, bis es
funktioniert. Optimieren kann er das später, wenn er mehr Erfahrung hat
und es überhaupt von Interesse ist.
Georg
Philipp K. schrieb:> Es kommt auch auf den GLCD chip an
Nein, eigentlich nicht.
Und warum nicht?
Nun, weil man, um sinnvoll ein Grafik-Display ausnutzen zu können, im
RAM des µC einen Bildspeicher vorhalten sollte, auf den die diversen
Grafikroutinen ihr Zeugs zeichnen. Die Übertragung von diesem
Bildspeicher in's Display ist dabei eine völlig andere Ebene.
Auf diese Weise trennt man die Lowlevel-Angelegenheiten (z.B. Transport
der Pixel per SPI o.ä. zum Display) von der nächst höheren Schicht (z.B.
Kreise, Linie, Flächen zeichnen, Schrift zeichnen, Bilder zeichnen).
Diese Schicht ist dann nur noch wenig hardwareabhängig (nur noch
Pixelanzahl X und Y, sowie Anzahl der Farben). Und auf diese Schicht
setzt dann die nächste Schicht auf: grafische Elemente sich darstellen
lassen (Buttons, Frames, Labels, Edits, Checkboxen, usw.)
So. und aus alldem sieht man auch, daß es für grafische Displays eine
gewisse Mindestgröße des µC gibt, unterhalb derer man so ein Display
zwar prinzipiell ansteuern kann, aber nicht mehr sinnvoll verwenden
kann, eben weil der µC damit bereits überfordert ist.
W.S.
> Nein, eigentlich nicht.
Eigentlich schon. Mancher kann naemlich blitten.
Dann reduziert sich der Aufwand ein Zeichen zu schreiben auf:
- Komplettes Zeichen in den Off-Display-Speicher schreiben.
- Zeichen auf die Zielposition blitten.
Wenn der komplette Zeichensatz ins Off-Display-RAM passt,
muss man den natuerlich nur einmal kopieren.
NichtWichtig schrieb:> Spannend
Ach nö.
Soweit ich mich erinnere, können die besseren Chips von Solomon sowas.
Aber sowas ist umständlich. Man gibt die Koordinate vor, ebenso die
Fensterbreite und -höhe. Dann muß man "bloß" noch die Pixel dort
hineinfüllen, also entweder die Hintergrundfarbe oder die
Vordergrundfarbe. Wenn die je 6 Bit RGB oder größer ist und der µC ein 8
Bitter, dann wird das schon ein Klimmzug - selbst in Assembler. Wie das
bei Solomon mit Palettenmodi aussieht, weiß ich momentan nicht. Ach,
lies mal selber.
W.S.