Hi,
habe für ein Projekt die ks0108 Lib aus dem Wiki
(http://www.mikrocontroller.net/articles/KS0108_Library) auf einen PIC
Controller portretiert (war relativ einfach), jedoch habe ich ein
Problem mit der Fontausgabe:
Ich habe mir einen Symbolfont erstellt, um Symbole auszugeben. Wenn ich
so ein Symbol am unteren Rand drucken will, werden sie nach acht Bit in
vertikaler Richtung abgeschnitten und die restlichen Punkte oben am
Display angezeigt (siehe Anhang). Selbe Problem tritt auch mit den
mitgelieferten Fonts auf. Der Font selber ist in Ordnung denk ich, da
wenn ich das Symbol weiter oben drucke (wie das Speaker Symbol), ist die
Darstellung einwandfrei (habe zum Test den Speaker unten platziert, dann
war auch dieser abgeschnitten). Was kann der Fehler in der Funktion
sein?
Weiß niemand was? Ich sehe den Fehler in der Routine nicht, hat jemand
anders nicht auch schon das Problem mit dieser Library gehabt, oder
liegt der Fehler ganz wo anders?
Hallo,
genau genommen bricht er ja nicht am Ende des Displays um, sondern schon
bei Zeile 60. Sieht nach einem Fehler im Shiften des 2.Bytes aus.
Wie hoch sind deine Zeichen?
Ist oberhalb der Symbole noch Leerraum?
Gib dein Symbol mal ab der Pos bevor der Fehler auftritt Schritt für
Schritt ein Pixel weiter unten aus um zu sehen wie sich das genau
verhält.
Sascha
Was mir noch aufgefallen ist: Der "GLCD FontCreater 2" trägt für die
Höhe -10 ein, ich musste das immer auf +10 korrigieren. Ist das ein Bug
von dem Programm?
Michael M. schrieb:> Der "GLCD FontCreater 2" trägt für die> Höhe -10 ein, ich musste das immer auf +10 korrigieren. Ist das ein Bug> von dem Programm?
Hänge mal die komplette .h Datei an, die der FontCreator ausgibt.
Bei mir stimmt alles, nur ein "static" muss ich noch manuell einfügen.
Obwohl ich 10 eingestellt habe, kommt -10 raus: "#define NEW_FONT_HEIGHT
-10" und "0xF6, // height"
Habe allerdings eine Änderung in dem Font Creator Template gemacht,
damit er "const char ..." schreibt (hatte auch "const static char ..."
aber da war der Fehler der selbe (Compiler ist der XC8)
Allerdings denk ich nicht, dass dies den besagten Fehler mit der Ausgabe
produziert, da das Symbol ja nur im unteren Bereich nicht richtig
angezeigt wird
Hallo,
ändert denn das was, wenn du die Höhe auf +10 korrigierst? Ich glaube
nicht, das das sinnvoll funktionieren kann mit -10.
An der Stelle
1
uint8_theight=ks0108Font[FONT_HEIGHT];
wird aus -10 schon mal +246
Keine gute Idee ist es den Font mit Char 0x00 beginnen zu lassen, da ein
Nullbyte das Ende eines Strings makiert. Wenn du nur mit putChar das
eine Zeichen ausgibst, fällt das erst mal nicht weiter auf.
Sascha
>Bis zur y-Koordinate 47>sind die Symbole fehlerfrei, ab dann werden sie abgeschnitten.
Eigentlich ist es logisch das sie ab 48 abgeschnitten werden.
Das Programm gibt immer 8 Pixel senkrecht aus. Deine Zeichen sind
real 16 Bits hoch. Wenn du bei 48 beginnst endet es bei Koordinate 64.
Das Display geht aber nur von 0..63. Irgendwo im Programm wird bei der
Ausgabe des unteren Teils deines Fonts ein Überlauf auf 0 stattfinden.
Und dann malt er dir teile deines Fonts wieder vom oberen Teil des
Displays beginnend.
Sascha Weber schrieb:> Hallo,>> ändert denn das was, wenn du die Höhe auf +10 korrigierst? Ich glaube> nicht, das das sinnvoll funktionieren kann mit -10.> An der Stelleuint8_t height = ks0108Font[FONT_HEIGHT];> wird aus -10 schon mal +246>> Keine gute Idee ist es den Font mit Char 0x00 beginnen zu lassen, da ein> Nullbyte das Ende eines Strings makiert. Wenn du nur mit putChar das> eine Zeichen ausgibst, fällt das erst mal nicht weiter auf.>> Sascha
Das habe ich bereits schon gemacht, wie du aus meinem Auszug weiter Oben
siehst.
Sascha Weber schrieb:> ich nochmal,>> hast du eine Möglichkeit die Daten die ans Display gehen auszugeben> (seriell)?>> Sascha
Kann ich mal mit nem Array im Debugmodus erstellen
holger schrieb:>>Bis zur y-Koordinate 47>>sind die Symbole fehlerfrei, ab dann werden sie abgeschnitten.>> Eigentlich ist es logisch das sie ab 48 abgeschnitten werden.> Das Programm gibt immer 8 Pixel senkrecht aus. Deine Zeichen sind> real 16 Bits hoch. Wenn du bei 48 beginnst endet es bei Koordinate 64.> Das Display geht aber nur von 0..63. Irgendwo im Programm wird bei der> Ausgabe des unteren Teils deines Fonts ein Überlauf auf 0 stattfinden.> Und dann malt er dir teile deines Fonts wieder vom oberen Teil des> Displays beginnend.
Hmm ich seh nur irgendwie den Fehler nicht, es handelt sich wie gesagt
im die Lib aus dem Wiki hier, hat da noch niemand anders das selbe
Problem damit gehabt und weiß wo der Fehler liegt?
>Hmm ich seh nur irgendwie den Fehler nicht, es handelt sich wie gesagt>im die Lib aus dem Wiki hier, hat da noch niemand anders das selbe>Problem damit gehabt und weiß wo der Fehler liegt?
Scheinbar nicht. Könntest du bestätigen das erst ab 49 abgeschnitten
wird?
Das Problem taucht wohl immer nur auf wenn
die Zeichen unten aus dem Displaybereich rausragen. Das passt mit
deiner 47 aber nicht.
hier findet deine Rücksetzung auf 0 statt.
Dieser Code kommt nicht damit klar, dass du ganz unten am Display noch 2
Bits aus dem Character hinmalen müsstest, um das ganze Zeichen zu sehen,
da deine Zeichen 10 Pixel hoch sind.
Mit deiner Positionierung müsstest du die virtuelle Zeichenposition
unter die 63 setzen, damit die obersten beiden Bits noch in der
Zeichenfläche liegen. Das aber lässt diese Positionierfunktion nicht zu
und setzt dir die y-Position auf 0.
Die Behandlung von Font-Höhen, die kein Vielfaches von 8 ist, ist etwas
zu 'schwach' implementiert. Den 'Fehler' im Fonteditor diesbezüglich
auszugleichen reicht nicht.
D.h. wenn ich es mir recht überlege, ist das eigentlich kein Fehler. Das
scheint tatsächlich so beabsichtigt zu sein, dass man nicht Vielfache
von 8 dadurch realisiert, dass man die letzten Bytes nicht bitmässig
zurechtschiebt, sondern diese Bytes dann eben nicht um 8 tiefer ausgibt,
sondern nur noch um die fehlende Bitzahl.
(Ich weiß, das klingt jetzt konfus. Es ist schwer in Worte zu kleiden.
Ich versuchs nochmal mit einer Zeichnung)
Das hier sind deine Font-Daten für den Down-Character
1
0x20,0x60,0xE0,0xFE,0xFE,0xE0,0x60,0x20,0x00,0x00,0x00,0x40,0x40,0x00,0x00,0x00,// 11 Down
interessant ist die 2.te Page:
1
0x00,0x00,0x00,0x40,0x40,0x00,0x00,0x0
anstelle der 0x40, hätte ich eigentlich 0x01 erwartet, denn das ist
genau das, was bei einer Zeichenhöhe von 10 Pixel fehlt um den letzten
'Querstrich' unten zu kriegen, wenn die Pixel senkrecht übereinander
liegen und das jeweilige LSB 'oben' liegt.
1
+---+---+---+---+---+---+---+---+
2
| | | | # | # | | | | Byte 0, Bit 0 +
3
+---+---+---+---+---+---+---+---+ |
4
| | | | # | # | | | | Byte 0, Bit 1 |
5
+---+---+---+---+---+---+---+---+ |
6
| | | | # | # | | | | Byte 0, Bit 2 |
7
+---+---+---+---+---+---+---+---+ |
8
| | | | # | # | | | | Byte 0, Bit 3 |
9
+---+---+---+---+---+---+---+---+ |
10
| | | | # | # | | | | Byte 0, Bit 4 |
11
+---+---+---+---+---+---+---+---+ |
12
| # | # | # | # | # | # | # | # | Byte 0, Bit 5 |
13
+---+---+---+---+---+---+---+---+ |
14
| | # | # | # | # | # | # | | Byte 0, Bit 6 |
15
+---+---+---+---+---+---+---+---+ |
16
| | | # | # | # | # | | | Byte 0, Bit 7 |
17
+---+---+---+---+---+---+---+---+ |
18
20 60 E0 FE FE E0 60 20 |
19
|
20
+---+---+---+---+---+---+---+---+ |
21
| | | | # | # | | | | Byte 1, Bit 0 |
22
+---+---+---+---+---+---+---+---+ |
23
| | | | | | | | | Byte 1, Bit 1 v
24
+---+---+---+---+---+---+---+---+------------------------- 10 Bit
25
| | | | | | | | | Byte 1, Bit 2
26
+---+---+---+---+---+---+---+---+
27
| | | | | | | | | Byte 1, Bit 3
28
+---+---+---+---+---+---+---+---+
29
| | | | | | | | | Byte 1, Bit 4
30
+---+---+---+---+---+---+---+---+
31
| | | | | | | | | Byte 1, Bit 5
32
+---+---+---+---+---+---+---+---+
33
| | | | | | | | | Byte 1, Bit 6
34
+---+---+---+---+---+---+---+---+
35
| | | | | | | | | Byte 1, Bit 7
36
+---+---+---+---+---+---+---+---+
37
00 00 00 01 01 00 00 00
Das ist das, was ich in den Fontdaten erwartet hätte.
Statt dessen findet sich aber das hier
Die restlichen beiden Zeilen, die fehlen um die 8 Bit auf 10 Bit
Zeichenhöhe zu ergänzen, sind offenbar in den Bits 6 und 7 des zweiten
Bytes codiert. Warum 6 und 7? Weil das 2 Bit sind und 2 Bit fehlen um
die geforderten 10 Pixel Höhe zu erreichen.
D.h. was man tun müsste ist, die ersten 8 Bits ausgeben, danach die
Schreibposition um lediglich 2 Pixel nach unten setzen und das jeweilige
2.te Byte drüber-odern, damit (um beim Beispiel zu bleiben) eine
durchgehende Pixelreihe von 9 senkrechten Pixel entsteht.
Was passiert im Code statt dessen?
Das hier
1
if(height<(i+1)*8){
2
data>>=(i+1)*8-height;
3
}
Er schiebt die 0x40 zurecht, so dass daraus die 0x01 werden, die ich
eigentlich in den Font Daten erwartet hätte und geht dafür als Ausgleich
nicht 2 Pixel tiefer, sondern 8.
1
ks0108GotoXY(x,ks0108Coord.y+8);
Das funktioniert auch sonst (meistens) gut (*), bis auf den Fall, wo er
dann mit diesem 8-Pixel Versatz in y eben unten über die Display-grenze
rauskommt. Und Zack
1
if(y>63)y=0;
und damit ist dann das Kind in den Brunnen gefallen.
Der Code kommt nicht damit zurecht, wenn ein Zeichen, obwohl es
rechnerisch aufs Display passen würde, nicht mehr mit dem letzten Byte
aufs Display passt, weil die Schreibposition unterhalb der Displaygrenze
zu liegen kommt um in deinem Fall die fehlenden 2 Bits zu schreiben, die
er sich zuvor ins LSB verschoben hat.
Ich denke, es müsste genügen, diesen Schiebecode zu entfernen, dafür
muss allerdings das letzte Byte in einer Spalte anders behandelt werden
(Pixel setzen / löschen) und vor allen Dingen muss die Positionierung
dieses letzten Bytes anders behandelt werden. Diese Byte 'überlappt'
dann das senkrecht über ihm liegende, was das korrekte Pixelsetzen bzw.
löschen erschwert. Du kannst dann da in diesen letzten beiden Zeilen
nicht mehr einfach ...
1
if(ks0108FontColor==BLACK){
2
ks0108WriteData(data);
3
}else{
4
ks0108WriteData(~data);
5
}
... 8 senkrechte Pixel rausblasen und alles ist gut.
(*) denkfehler: wird invers geschrieben funktioniert es eben nicht mehr
gut, sondern lausig schlecht. Damit das alles korrekt funktioniert, MUSS
die Behandlung von "Nicht Vielfache von 8" Zeichenhöhen komplett
überarbeitet werden. Momentan ist das eine Quick&Dirty Lösung, die, wenn
man genauer schaut eben nicht sorgenfrei funktioniert.
holger schrieb:> Scheinbar nicht. Könntest du bestätigen das erst ab 49 abgeschnitten> wird?
Hmm.
Hab ich mich verzählt?
wenn ich y runterzähle, beginnt die Oberkante dieser speziellen Zeichen
an Pixelposition y=53.
>> Scheinbar nicht. Könntest du bestätigen das erst ab 49 abgeschnitten>> wird?>>Hmm.>Hab ich mich verzählt?>wenn ich y runterzähle, beginnt die Oberkante dieser speziellen Zeichen>an Pixelposition y=53.
In Bezug auf sein Bild stimmt das so. Er hat aber noch kein Bild gezeigt
wo noch alles gut ist und ab wann das übel anfängt. Deshalb hab ich
ja gefragt wo genau das Problem anfängt.
Das Problem ist wohl das der Code eben nicht wirklich Pixeln kann.
Bei seiner 10 Pixel Zeichenhöhe werden immer zwei komplette
Bytes ausgegeben. So malt der KS108 nun mal;)
int ks0108PutChar(char c) {
uint8_t bytes = (height+7)/8;
// last but not least, draw the character
for(uint8_t i=0; i<bytes; i++) {
Und das passt halt schon ab 49 nicht mehr.
holger schrieb:>>> Scheinbar nicht. Könntest du bestätigen das erst ab 49 abgeschnitten>>> wird?>>>>Hmm.>>Hab ich mich verzählt?>>wenn ich y runterzähle, beginnt die Oberkante dieser speziellen Zeichen>>an Pixelposition y=53.>> In Bezug auf sein Bild stimmt das so. Er hat aber noch kein Bild gezeigt> wo noch alles gut ist und ab wann das übel anfängt. Deshalb hab ich> ja gefragt wo genau das Problem anfängt.
Ah, ok.
Ich war mit der Analyse so beschäftigt, dass ich anscheinend die Hälfte
nicht gelesen habe :-)
Scheint so, als ob wir beide ins gleiche Horn stossen.
Der Code ist ein bißchen zu vereinfacht geschrieben worden und kommt mit
Sonderfällen, wie eben einem 10 Bit hohen Font nicht wirklich korrekt
klar. Da müsste man nachbessern.
>Ah, ok.>Ich war mit der Analyse so beschäftigt, dass ich anscheinend die Hälfte>nicht gelesen habe :-)>Scheint so, als ob wir beide ins gleiche Horn stossen.
Exakt. Wenn seine Font Bitmap unten auch nur einen Pixel
übersteht geht es vermutlich los mit den Anzeigefehlern.
Seine Fonthöhe ist zwar nur 10 Pixel, aber wegen der
Ausgabemethode des Programms beginnt das Problem schon 6 Pixel früher.
holger schrieb:>>Ah, ok.>>Ich war mit der Analyse so beschäftigt, dass ich anscheinend die Hälfte>>nicht gelesen habe :-)>>Scheint so, als ob wir beide ins gleiche Horn stossen.>> Exakt. Wenn seine Font Bitmap unten auch nur einen Pixel> übersteht geht es vermutlich los mit den Anzeigefehlern.> Seine Fonthöhe ist zwar nur 10 Pixel, aber wegen der> Ausgabemethode des Programms beginnt das Problem schon 6 Pixel früher.
Exakt.
Und das ist nicht das einzige Problem.
Bei inverser Darstellung wird anstelle eines 10 Pixel hohen Zeichens ein
16 Pixel hoher Bereich invers dargestellt, in dem das Zeichen im oberen
Teil festgenagelt ist. Sprich, er kriegt eine 6-Pixel hohe inverse
'Unterlänge'.
Ne, ne. Da muss nachgebessert werden. Das ist ein bischen zu blauäugig
programmiert.
Karl Heinz Buchegger schrieb:> Teil festgenagelt ist. Sprich, er kriegt eine 6-Pixel hohe inverse> 'Unterlänge'.
So würde man das Problem IMHO sogar noch besser sehen. Sobald dieser
inverse Klotz, der eigentlich gar nicht mehr zum Zeichen gehört die
Unterkante des Display berührt, geht der Tanz los.
Hi, ich bedanke mich für die Antworten, besonders an kbuchegg. Ich
konnte das Problem mit hilfe seiner Bilchen lösen. Der Fehler selber lag
gar nicht an der oben genannte Funktion, sondern an der Funktion
1
voidks0108WriteData(uint8_tdata)
Ursprünchlich sah der Hauptteil dieser Funktions so aus (Ausschnitt):
1
voidks0108WriteData(uint8_tdata){
2
/*...*/
3
yOffset=ks0108Coord.y%8;
4
if(yOffset!=0){
5
// first page
6
cmdPort=LCD_CMD_PORT;// save command port
7
displayData=ks0108ReadData();
8
9
LCD_CMD_PORT=cmdPort;// restore command port
10
LCD_DATA_DIR=0x00;// data port is output
11
12
displayData|=data<<yOffset;
13
if(ks0108Inverted)
14
displayData=~displayData;
15
LCD_DATA_OUT=displayData;// write data
16
ks0108Enable();// enable
17
18
// second page
19
ks0108GotoXY(ks0108Coord.x,ks0108Coord.y+8);
20
21
displayData=ks0108ReadData();
22
23
LCD_CMD_PORT=cmdPort;// restore command port
24
LCD_DATA_DIR=0x00;// data port is output
25
26
displayData|=data>>(8-yOffset);
27
if(ks0108Inverted)
28
displayData=~displayData;
29
LCD_DATA_OUT=displayData;// write data
30
ks0108Enable();// enable
31
32
ks0108GotoXY(ks0108Coord.x+1,ks0108Coord.y-8);
33
}else{
34
if(ks0108Inverted)
35
data=~data;
36
LCD_DATA_OUT=data;// write data
37
ks0108Enable();// enable
38
ks0108Coord.x++;
39
}
40
/*...*/
41
}
Der Fehler selber tratt nun hier auf:
1
// second page
2
ks0108GotoXY(ks0108Coord.x,ks0108Coord.y+8);
An dieser besagten Stelle tritt ein Überlauf der Y-Koordinate auf, wenn
man an eine Koordinate > 55 schreiben will (d.h. mitten in die letzte
Page 7). Das wär jetzt noch nicht so schlimm, da er durch eine
Fehlerbehandlung in der ks0108GotoXY-Funktion die x-Koordinate 0 setzen
würde und dann in die Page 0 das wieder schreiben würde, was er auch
liest (deswegen ist bei jedem Zeichen die erste Spalte immer fehlerfrei
gewesen).
Allerdings will er nach der Ausgabe die y-Koordinate um 8 verringern,
damit er wieder da steht, wo er zu beginn war:
1
ks0108GotoXY(ks0108Coord.x+1,ks0108Coord.y-8);
Jetz ist aber die y-Koordinate 0 gewesen:
0-8 = 248 (u_int8)
Die Folge ist, dass er wegen der Fehlerprüfung y wieder zu 0 setzen wird
und damit die nächste Ausgabe fälschlicherweise in die Page 0 führt.
Mein sehr einfache Lösung sieht so aus:
1
// second page
2
if((ks0108Coord.y+8)<64)
3
{
4
ks0108GotoXY(ks0108Coord.x,ks0108Coord.y+8);
5
6
displayData=ks0108ReadData();
7
8
LCD_CMD_PORT=cmdPort;// restore command port
9
LCD_DATA_DIR=0x00;// data port is output
10
11
displayData|=data>>(8-yOffset);
12
if(ks0108Inverted)
13
displayData=~displayData;
14
LCD_DATA_OUT=displayData;// write data
15
ks0108Enable();// enable
16
17
ks0108GotoXY(ks0108Coord.x+1,ks0108Coord.y-8);
18
}else
19
ks0108GotoXY(ks0108Coord.x+1,ks0108Coord.y);
Damit wird ersten die unnötige Ausgabe in die Page 0 unterbunden und
zugleich verhindert, dass y zu 0 wird.
Vollständige Funktion: