Hallo zusammen,
ich versuche mich gerade an einem GLCD Display 128*64 Pixel, Controller
SSD1305.
Ich habe einen Beispielcode aus dem Netz genommen und ein wenig damit
rumexpermentiert. Grundsätzlich funktioniert das auch.
Ich habe nun aber ein Problem mit Schriften.
Bei dem Beispielcode waren zwei Schriften dabei einmal 8x16 und einmal
6x8. Die Ausgabe funktioniert auch einwandfrei. Ich würde nun gerne noch
andere Schriften ausgeben, also andere Größe z.B. 4x6 oder so.
Da liegt jetzt mein Problem. Hier im Forum gibt es ja genug Schriften
für LCDs. Wenn ich mir nun so eine Schrift nehme und ausgebe,
funktioniert das nicht. Es irgendwas ausgegeben, aber kein Text bei den
von mir erstellen Schriften.
Wäre klasse, wenn mir da jemand weiterhelfen könnte.
Im Anhang einmal die Datei mit den Schriften und meine Funktionen für
das Display.
Grüße
Thorsten
Ich nochmal,
ganz veressen zu schreiben. Den Code habe ich hier aus dem Forum, leider
war ich so schlau mir keine lesezeichen zum Thread zu setzen.
Im Code war noch der entsprechende Hinweis. Vielleicht hat es ja schon
einmal jemand gesehen:
Thorsten schrieb:> Da liegt jetzt mein Problem. Hier im Forum gibt es ja genug Schriften> für LCDs. Wenn ich mir nun so eine Schrift nehme und ausgebe,> funktioniert das nicht. Es irgendwas ausgegeben, aber kein Text bei den> von mir erstellen Schriften.
Tja. Du musst natürlich schon drauf achten, wie die Fonts aufgebaut sind
bzw. wie die Funktion, die letzten Endes die Buchstaben ausgibt, die
Bytes aus den Fonts auseinander nimmt.
> Wäre klasse, wenn mir da jemand weiterhelfen könnte.
Das kannst du auch selber. Blöderweise hat derjenige, der deine Fonst
gebaut hat, so ziemlich das Dämlichste gemacht, was er hätte machen
können. Er hat Byteangaben, bei denen es eine Bit-Pixel Korrelation
gibt, als Dezimalzahlen angeschrieben anstatt als wesentlich näher
liegenden Hex-Zahlen. Das beschert dir jetzt eine Zusatzarbeit. Aber so
schlimm ist es auch wieder nicht.
Lass uns mal so einen Font ansehen. Wie beginnt er
1
constunsignedcharfont_8X16[font_8X16_LEN]PROGMEM=
2
{
3
70,86,32,255,8,16,2,16,
4
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
5
0,0,0,252,252,0,0,0,0,0,0,51,51,0,0,0,
6
0,252,252,0,0,252,252,0,0,0,0,0,0,0,0,0,
7
....
Auffällig ist, das die erste Zeile anders aussieht, als die anderen. Die
erste zeile besteht aus 8 Bytes, alle weiteren aus 16 Bytes. Hmm. Die 16
kommen einem bekannt vor. Was war noch mal die Font-'Größe'? 8 mal 16.
So, so. Ein Zeichen ist also 8 Pixel breit (oder hoch) und 16 Pixel hoch
(oder breit). Ob die letztere 16 was damit zu tun hat, dass da jeweils
16 Bytes pro Zeile sind? Wir werden sehen.
Auffällig ist trotzdem, dass die erste Zeile anders aussieht. Was könnte
das sein?
Na, ja. So eine Funktion, die Zeichen ausgibt, wird ja wohl ein paar
Informationen brauchen. Wie zum Beispiel: wie breit ist ein Zeichen. Wie
hoch ist ein Zeichen. etc. etc. Irgendwo muss diese Inforamtion ja
stehen. Und da ist es wohl auch naheliegend, dass diese Zeile diese
Information (und weitere) beinhalten könnte.
Wie könnte man das klären?
Einfach. Du hast ja den Code. Wenn du deiner Codebasis diese Daten
übergibst, dann wird sich da ja wohl entsprechender Code finden, der
diese Information ausliest. Und mit ein bischen Glück hat der Autor des
Codes da vernünftige Variablennamen gewählt, mit denen man was anfangen
kann.
Schauen wir doch mal in den Code. Was findet sich da?
OK. Der Autor war nicht so freundlich, sondern hat das ein wenig
versteckt
1
//calculate positon of data in font array
2
//(data*Bytes pro Char)-(start of chars * bytes pro char)+bytes for header
font_pos-=pgm_read_byte(font+4);//subtract pixels for one char, because it's added again in loop
font + 7 ist nichts anderes als &font[7]. Also das 8. Byte im Font.
Also das hier
1
// 0 1 2 3 4 5 6 7
2
70, 86, 32,255, 8, 16, 2, 16,
3
^
4
|
Also 16.
Was stand da im Kommentar?
1
//(data*Bytes pro Char) ....
Bytes pro Char. Ja das könnte hinkommen. Bei einem Font der 16 Pixel
breit (oder hoch) ist, würde man erwarten, dass jedes Zeichen auch 16
Bytes breit ist. Passt soweit.
Wie gings weiter im Kommentar
1
....(startofchars*bytesprochar)....
das korrespondiert recht augenscheinlich mit dem hier
die font + 7 kennen wir schon, also wird wohl font + 2, vulgo &font[2],
die 'start of chars' sein. Schaun wir mal, was da im Datenfeld steht
1
// 0 1 2 3 4 5 6 7
2
70, 86, 32,255, 8, 16, 2, 16,
3
^
4
|
32.
Gut. Jetzt wissen wir, das im ASCII Code die ersten 32 Zeichen
Steuerzeichen sind und die eigentlich darzustellenden Zeichen erst mit
dem 33. zeichen beginneb. Das trägt daher den ASCII Code 0x20 und ist,
ASCII Kenner wissen das, ein Leerzeichen.
D.h. die 32 machen durchaus Sinn. Zumindest ist das eine Zahl, mit der
man was anfangen kann. Da dieser Term vom bisherigen abgezogen wird,
kann man daraus schliessen, dass die Idee wohl darin besteht, ganz
einfach eine Tabelle mit den Pixeldaten zu haben. Der ASCII Code eines
Zeichens ist Index in diese Byte Tabelle. Da jedes Zeichen 16 Byte
benötigt, beginnt also das Zeichen mit dem Code 0 an Position 0, das mit
dem Code 1 an Position 16, das mit dem Code 2 an Position 32 usw. usw.
Der Autor des Codes, will aber die nicht darstellbaren Zeichen nicht in
der Tabelle haben, verbraucht nur Platz. Also hat er die ersten 32
Zeichen einfach ausgelassen. D.h. aber er muss eine Korretur anbringen.
Denn das erste darstellbare Zeichen (wir erinnern uns, das war ein
Leerzeichen), hat ja den Code 32. Damit dessen Beschreibung in der
Tabelle an der Position 0 startet, muss er also vom vbisherigen 16*32
wieder abziehen, damit die Rechnung ergibt, dass das Zeichen mit dem
Code 32 an der Position 0 in der Tabelle anfängt, das mit dem Code 33 an
der Position 16, das mit dem Code 34 an der Position 32, das mit Code 35
an der Position 48, usw. usw.
Und zu guter leztzt zählt er in dieser c-Zeile noch 8 dazu
im Kommentar steht da lapidar: wegen der Header Größe.
Nun die Header-Größe, das ist nichts anderes als die Font-Beschreibung
in der ersten Zeile. Und das sind 8 Bytes. Stimmt auffallend überein.
Damit ist die Zeile
komplett analysiert. Wir wissen was da passiert und warum es passiert
und wie der Zusammenhang zu
1
constunsignedcharfont_8X16[font_8X16_LEN]PROGMEM=
2
{
3
70,86,32,255,8,16,2,16,
aussieht. 2 dieser 8 Angaben können wir bereits deuten. Die 8 die da in
den Daten vorkommt, die können wir auch einfach mal raten. Da der Font
ein 8 mal 16 Font ist, wird wohl diese 8 für die Breite (oder Höhe)
eines Zeichens stehen. Mit deinem 2.ten Font kannst du das ja mal
kontrollieren.
Aber wie sind die Zeichen aufgebaut.
Nehmen wir das Zeichen mit dem Code 33. Das ist laut ASCII Tabelle ein
!. Da wir die Indexberechnung ins Array nachvollziehen können, wissen
wir auch das diese Bytes
1
constunsignedcharfont_8X16[font_8X16_LEN]PROGMEM=
2
{
3
70,86,32,255,8,16,2,16,
4
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
5
0,0,0,252,252,0,0,0,0,0,0,51,51,0,0,0,<---diehier
wohl irgendwie ein Rufzeichen beschreiben.
Wie gesagt: Dezimal ist hier komplett dämlich, denn hier geht es um
Pixel. Und wenn wir mal davon ausgehen, dass 1 Pixel eine Entsprechung
zu einem Bit haben wird, dann muss man diese Zahlen
1
0,0,0,252,252,0,0,0,0,0,0,51,51,0,0,0,
in ihrer Bitdarstellung sehen. Mit Hex wäre das leichter umzusetzen,
aber mit einem Taschenrechner gehts auch so. Lass uns die 16 Zahlen mal
in ihrer Bitdarstellung ansehen
1
0 00000000
2
0 00000000
3
0 00000000
4
252 11111100
5
252 11111100
6
0 00000000
7
0 00000000
8
0 00000000
9
0 00000000
10
0 00000000
11
0 00000000
12
51 00110011
13
51 00110011
14
0 00000000
15
0 00000000
16
0 00000000
hmm. auf den ersten Blick ist da jetzt noch kein Rufzeichen erkennbar.
Oder doch? Auffällig ist, dass es da 2 Blöcke gibt. Lass uns die mal
nebeneinander setzen
1
00000000 00000000
2
00000000 00000000
3
00000000 00000000
4
00110011 11111100
5
00110011 11111100
6
00000000 00000000
7
00000000 00000000
8
00000000 00000000
Doch. Ja. Wenn ich den Kopf 90° nach rechts zur Seite drehe, dann kann
ich da schon ein Rufzeichen erkennen. Der Punkt, das ist der 2 mal 2
Blick aus 1-sen im linken Block und der Strich geht über die Lücke in
den Block rechts rein.
Das ist doch schon mal eine Spur. Mal sehen. Ob das woanders auch
funktioniert.
Ein 'A' hat den ASCII Code 65 dezimal. Mal in die Formel eingesetzt
(65 * 16) - ( 32 * 16 ) + 8
ergibt 536
Im Datenarray mal das Byte an der Stelle 536 suchen.
Das ist die Zeile hier
wenn alles klappt, dann müssten wir auf ganz ähnliche Weise ein 'A'
hervorzaubern können. Also wieder: die Zahlen binär anschreiben
1
0 00000000
2
240 11110000
3
248 11111000
4
28 00011100
5
28 00011100
6
248 11111000
7
240 11110000
8
0 00000000
9
0 00000000
10
63 00111111
11
63 00111111
12
3 00000011
13
3 00000011
14
63 00111111
15
63 00111111
16
0 00000000
der nächste Schritt war, die 16 Zeilen in 2 8-er Blöcke zu zerteilen und
den unteren Block links vom oberen Block anzuschreiben
1
00000000 00000000
2
00111111 11110000
3
00111111 11111000
4
00000011 00011100
5
00000011 00011100
6
00111111 11111000
7
00111111 11110000
8
00000000 00000000
ja, doch. Den Kopf um 90° drehen und ich kann da ein 'A' erkennen. die
beiden senkrechten, oben die Verbindung und in der Mitte (ganz rechts im
linken Block) der Querstrich. So
1
111111 1111
2
111111 11111
3
11 111
4
11 111
5
111111 11111
6
111111 1111
sieht man es noch besser.
Ich denke, damit ist klar, wie der Aufbau der Fontdaten ist.
Zumindest in diesem Beispiel mit den 16 Bytes pro Zeichen. Das sind 2
Blöcke zu je 8 Bit. Wobei interessanterweise ja auch hier im Header
1
constunsignedcharfont_8X16[font_8X16_LEN]PROGMEM=
2
{
3
70,86,32,255,8,16,2,16,
eine 2 vorgekommen ist. Unmittelbar vor der 16, welche ja die Anzahl der
Bytes pro Zeichen angegeben hat.
Ich denke, du siehst schon, wie man sowas angeht. Jetzt liegt es eben an
dir, dir die Fontdaten, die du gefunden hast dir auch mal näher
anzusehen. Entweder man kann die relativ einfach in diese Form hier
unwandeln, oder aber, wenn das gar nicht geht, dann schreibt man eben
wieder eine neue Ausgaberoutine. Aber die Anpassung wäre eigentlich
vernünftiger. Die kann ja auch ein PC-Programm machen.
Hat man den Aufbau der Fontdaten (egal welche) dann erst mal verstanden,
kann man auf dem Papier nachvollziehen, wie sich daraus letzten Endes
die schwarzen bzw. weissen Pixel ergeben, dann ist es auch nicht weiter
schwer, den zugehörigen C-Code zu lesen. Denn der muss ja dann nichts
weiter tun, als diese Daten in eine Form bringen, wie sie das LCD haben
will. Dazu muss man natürlich jetzt wieder wissen, wie das LCD seine
Angaben haben will. Malt dieses ein Byte (also 8 Bit) als eine Spalte
hin (mit hellen bzw. dunklen Pixeln) oder malt es das als 8
nebeneinander liegende Pixel hin (also quasi in einer Zeile).
Aber sich hinstellen und 'helft mir' rufen - das ist zu wenig. Ein
bischen was musst du schon auch selbst tun. So ist das nun mal, wenn man
programmieren will.
Hallo Thorsten,
ohne Code von dem neuen Font ist das zwar alles nur geraten aber vll
hilft es weiter. In deinem Beispiel haben die Schriftarten an Pos 0 ein
paar Einstellungen zum Array
unsigned int font_pos=0; //postion of data within the font array
Prüfe mal ob der neue Font dazu kompatibel ist. Ich habe jetzt nicht
überprüft ob dein Code mit Fonts umgehen kann die als Höhe kein
Vielfaches von 8 sind.
Möglich ist auch, dass die Bytedarstellung (Mapping Bit->Pixel) auf dem
LCD des neuen Fonts eine andere ist.
Gruß Thomas
Hallo,
auch wenn ich nun weiß, dass die neue Schrift nicht zu meinem Format
passt hänge ich sie mal an.
Vielen Dank schonmal. Ich muss mir das mal zu Gemüte führen und sehen,
dass ich meine Schrift entsprechend angepasst bekomme. Vielleicht gibt
es ja auch einen entsprechenden FontGenerator oder so.
Grüße