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
Hallo Georg,
>> Wenn du schon pixelweise arbeitest (ist halt langsam)
ich bin für jeden Vorschlag offen. Wie würdest du es machen ?
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?
:
Bearbeitet durch Moderator
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):
1 | unsigned
|
2 | draw_char(FONT_INFO *f, unsigned sx, unsigned sy, unsigned c) |
3 | {
|
4 | unsigned height, width, x, y, bits; |
5 | unsigned char *p; |
6 | |
7 | if (c == ' ') |
8 | return f->space_width; |
9 | |
10 | if (c < f->first || c > f->last) |
11 | return 0; |
12 | |
13 | c -= f->first; |
14 | height = f->height; |
15 | width = f->descriptors[c].width; |
16 | p = f->bitmap + f->desciptors[c].offset; |
17 | |
18 | bits = 0; // avoid warning |
19 | for (y = 0; y < height; ++y) |
20 | for (x = 0; x < width; ++x) |
21 | {
|
22 | if (x % 8 == 0) |
23 | bits = *p++; |
24 | if (bits & 0x80) |
25 | setpixel(sx + x, sy + y) |
26 | bits <<= 1; |
27 | }
|
28 | |
29 | return width; |
30 | }
|
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.zip https://www.mikrocontroller.net/attachment/301321/Fonts-machen-2.zip Georg 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:
1 | void
|
2 | draw_string(FONT_INFO *f, unsigned sx, unsigned sy, unsigned char *s) |
3 | {
|
4 | while (*s) |
5 | sx += draw_char(f, sx, sy, *s++); |
6 | }
|
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.
Spannend: Zeig mal Beispiel-Displays die das können.
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.