Forum: Mikrocontroller und Digitale Elektronik ks0108 lib aus Wiki: Problem mit Fontausgabe


von Michael M. (schakal)


Angehängte Dateien:

Lesenswert?

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?
1
int ks0108PutChar(char c) {
2
  uint8_t width = 0;
3
  uint8_t height = ks0108Font[FONT_HEIGHT];
4
  uint8_t bytes = (height+7)/8;
5
  
6
  uint8_t firstChar = ks0108Font[FONT_FIRST_CHAR];
7
  uint8_t charCount = ks0108Font[FONT_CHAR_COUNT];
8
  
9
  uint16_t index = 0;
10
  uint8_t x = ks0108Coord.x, y = ks0108Coord.y;
11
  
12
  if(c < firstChar || c >= (firstChar+charCount)) {
13
    return 1;
14
  }
15
  c-= firstChar;
16
  
17
  // read width data, to get the index
18
  for(uint8_t i=0; i<c; i++) {
19
    index += ks0108Font[FONT_WIDTH_TABLE+i];
20
  }
21
  index = index*bytes+charCount+FONT_WIDTH_TABLE;
22
  width = ks0108Font[FONT_WIDTH_TABLE+c];
23
  
24
  // last but not least, draw the character
25
  for(uint8_t i=0; i<bytes; i++) {
26
    uint8_t page = i*width;
27
    for(uint8_t j=0; j<width; j++) {
28
      uint8_t data = ks0108Font[index+page+j];
29
      
30
      if(height < (i+1)*8) {
31
        data >>= (i+1)*8-height;
32
      }
33
      
34
      if(ks0108FontColor == BLACK) {
35
        ks0108WriteData(data);
36
      } else {
37
        ks0108WriteData(~data);
38
      }
39
    }
40
    // 1px gap between chars
41
    if(ks0108FontColor == BLACK) {
42
      ks0108WriteData(0x00);
43
    } else {
44
      ks0108WriteData(0xFF);
45
    }
46
    ks0108GotoXY(x, ks0108Coord.y+8);
47
  }
48
  ks0108GotoXY(x+width+1, y);
49
  
50
  return 0;
51
}

MFG Michael

von Michael M. (schakal)


Lesenswert?

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?

von Sascha W. (sascha-w)


Lesenswert?

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

von Michael M. (schakal)


Angehängte Dateien:

Lesenswert?

Die Zeichen sind 10 Pixel hoch (siehe Anhang). Bis zur y-Koordinate 47 
sind die Symbole fehlerfrei, ab dann werden sie abgeschnitten.

Hier die icons.h
1
/*
2
 *
3
 * Icons
4
 *
5
 * created with FontCreator
6
 * written by F. Maximilian Thiele
7
 *
8
 * http://www.apetech.de/fontCreator
9
 * me@apetech.de
10
 *
11
 * File Name           : test
12
 * Date                : 08.08.2013
13
 * Font size in bytes  : 9735
14
 * Font width          : 10
15
 * Font height         : 10
16
 * Font first char     : 0
17
 * Font last char      : 99
18
 * Font used chars     : 99
19
 *
20
 * The font data are defined as
21
 *
22
 * struct _FONT_ {
23
 *     uint16_t   font_Size_in_Bytes_over_all_included_Size_it_self;
24
 *     uint8_t    font_Width_in_Pixel_for_fixed_drawing;
25
 *     uint8_t    font_Height_in_Pixel_for_all_characters;
26
 *     unit8_t    font_First_Char;
27
 *     uint8_t    font_Char_Count;
28
 *
29
 *     uint8_t    font_Char_Widths[font_Last_Char - font_First_Char +1];
30
 *                  // for each character the separate width in pixels,
31
 *                  // characters < 128 have an implicit virtual right empty row
32
 *
33
 *     uint8_t    font_data[];
34
 *                  // bit field of all characters
35
 */
36
37
#ifndef NEW_FONT_H
38
#define NEW_FONT_H
39
40
#define NEW_FONT_WIDTH 10
41
#define NEW_FONT_HEIGHT 10
42
43
const char icons[] = {
44
    0x26, 0x07, // size
45
    0x0A, // width
46
    0x0A, // height
47
    0x00, // first char
48
    0x63, // char count
49
50
    // char widths
51
    0x06, 0x08, 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08,
52
    0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
53
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
54
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
55
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
56
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
57
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
58
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
59
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
60
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
61
62
    // font data
63
    0x78, 0x78, 0x78, 0xFC, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC0, // 0  Speaker
64
    0x7B, 0x4E, 0x4C, 0x9C, 0x62, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC0, 0x40, 0xC0, // 1  Mute
65
    0xFE, 0xFC, 0x78, 0x30, 0x00, 0xFE, 0x00, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, // 2  Play
66
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 3  Stopp
67
    0xFE, 0xFC, 0x78, 0x30, 0xFE, 0xFC, 0x78, 0x30, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, // 4  Next
68
    0xFE, 0x30, 0x78, 0xFC, 0xFE, 0x30, 0x78, 0xFC, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, // 5  Prev
69
    0x30, 0x30, 0x30, 0xFE, 0xFE, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, // 6  Plus
70
    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 7  Minus
71
    0x30, 0x78, 0xFC, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // 8  Left
72
    0x30, 0x30, 0x30, 0x30, 0xFE, 0xFC, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // 9  Right
73
    0x10, 0x18, 0x1C, 0xFE, 0xFE, 0x1C, 0x18, 0x10, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, // 10  Up
74
    0x20, 0x60, 0xE0, 0xFE, 0xFE, 0xE0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, // 11  Down
75
    0x20, 0xF0, 0x08, 0xC4, 0x42, 0xC4, 0x08, 0xF0, 0x20, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, // 12  Home
76
    0xFC, 0x80, 0x80, 0x00, 0xFE, 0xFC, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // 13  BalanceLeft
77
    0x30, 0x30, 0x78, 0xFC, 0xFE, 0x00, 0xFC, 0x64, 0x98, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // 14  BalanceRight
78
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 15
79
...
80
81
};
82
83
#endif


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?

von Martin K. (maart)


Lesenswert?

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.

von Michael M. (schakal)


Lesenswert?

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)
1
/*
2
 *
3
 * icons
4
 *
5
 * created with FontCreator
6
 * written by F. Maximilian Thiele
7
 *
8
 * http://www.apetech.de/fontCreator
9
 * me@apetech.de
10
 *
11
 * File Name           : Icons.h
12
 * Date                : 12.08.2013
13
 * Font size in bytes  : 9735
14
 * Font width          : 10
15
 * Font height         : -10
16
 * Font first char     : 0
17
 * Font last char      : 99
18
 * Font used chars     : 99
19
 *
20
 * The font data are defined as
21
 *
22
 * struct _FONT_ {
23
 *     uint16_t   font_Size_in_Bytes_over_all_included_Size_it_self;
24
 *     uint8_t    font_Width_in_Pixel_for_fixed_drawing;
25
 *     uint8_t    font_Height_in_Pixel_for_all_characters;
26
 *     unit8_t    font_First_Char;
27
 *     uint8_t    font_Char_Count;
28
 *
29
 *     uint8_t    font_Char_Widths[font_Last_Char - font_First_Char +1];
30
 *                  // for each character the separate width in pixels,
31
 *                  // characters < 128 have an implicit virtual right empty row
32
 *
33
 *     uint8_t    font_data[];
34
 *                  // bit field of all characters
35
 */
36
37
#ifndef ICONS_H
38
#define ICONS_H
39
40
#define ICONS_WIDTH 10
41
#define ICONS_HEIGHT -10
42
43
const char icons[] = {
44
    0x26, 0x07, // size
45
    0x0A, // width
46
    0xF6, // height
47
    0x00, // first char
48
    0x63, // char count
49
    
50
    // char widths
51
    0x06, 0x08, 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 
52
    0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
53
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
54
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
55
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
56
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
57
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
58
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
59
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
60
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
61
    
62
    // font data
63
    0x78, 0x78, 0x78, 0xFC, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC0, // 0  Speaker
64
    0x7B, 0x4E, 0x4C, 0x9C, 0x62, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC0, 0x40, 0xC0, // 1  Mute
65
    0xFE, 0xFC, 0x78, 0x30, 0x00, 0xFE, 0x00, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, // 2  Play
66
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 3  Stopp
67
    0xFE, 0xFC, 0x78, 0x30, 0xFE, 0xFC, 0x78, 0x30, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, // 4  Next
68
    0xFE, 0x30, 0x78, 0xFC, 0xFE, 0x30, 0x78, 0xFC, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, // 5  Prev
69
    0x30, 0x30, 0x30, 0xFE, 0xFE, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, // 6  Plus
70
    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 7  Minus
71
    0x30, 0x78, 0xFC, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // 8  Left
72
    0x30, 0x30, 0x30, 0x30, 0xFE, 0xFC, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // 9  Right
73
    0x10, 0x18, 0x1C, 0xFE, 0xFE, 0x1C, 0x18, 0x10, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, // 10  Up
74
    0x20, 0x60, 0xE0, 0xFE, 0xFE, 0xE0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, // 11  Down
75
    0x20, 0xF0, 0x08, 0xC4, 0x42, 0xC4, 0x08, 0xF0, 0x20, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, // 12  Home
76
    0xFC, 0x80, 0x80, 0x00, 0xFE, 0xFC, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // 13  BalanceLeft
77
    0x30, 0x30, 0x78, 0xFC, 0xFE, 0x00, 0xFC, 0x64, 0x98, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // 14  BalanceRight
78
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 15
79
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
80
    // ...
81
};
82
83
#endif

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

von Sascha W. (sascha-w)


Lesenswert?

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_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

von Sascha W. (sascha-w)


Lesenswert?

ich nochmal,

hast du eine Möglichkeit die Daten die ans Display gehen auszugeben 
(seriell)?

Sascha

von holger (Gast)


Lesenswert?

>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.

von holger (Gast)


Lesenswert?

>Eigentlich ist es logisch das sie ab 48 abgeschnitten werden.

Verdammt, eigentlich dürfte erst ab 49 abgeschnitten werden;)

von Michael M. (schakal)


Lesenswert?

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?

von holger (Gast)


Lesenswert?

>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.

von Karl H. (kbuchegg)


Lesenswert?

Ich denke das Problem liegt hier:
1
void ks0108GotoXY(uint8_t x, uint8_t y) {
2
  uint8_t chip = CHIP1, cmd;
3
  
4
  if(x > 127) x = 0;                // ensure that coordinates are legal
5
  if(y > 63)  y = 0;

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)

von Karl H. (kbuchegg)


Lesenswert?

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

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                        v
19
20
+---+---+---+---+---+---+---+---+
21
|   |   |   |   |   |   |   |   |   Byte 1, Bit 0            ----+
22
+---+---+---+---+---+---+---+---+                                |
23
|   |   |   |   |   |   |   |   |   Byte 1, Bit 1                |
24
+---+---+---+---+---+---+---+---+                                |  gilt
25
|   |   |   |   |   |   |   |   |   Byte 1, Bit 2                |
26
+---+---+---+---+---+---+---+---+                                |  nichts
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      v
36
+---+---+---+---+---+---+---+---+----------------------------
37
 00  00  00  40  40  00  00  00

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von holger (Gast)


Lesenswert?

>> 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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von holger (Gast)


Lesenswert?

>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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Michael M. (schakal)


Lesenswert?

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
void ks0108WriteData(uint8_t data)

Ursprünchlich sah der Hauptteil dieser Funktions so aus (Ausschnitt):
1
void ks0108WriteData(uint8_t data) {
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:
1
void ks0108WriteData(uint8_t data) {
2
  uint8_t displayData, yOffset, cmdPort;
3
4
#ifdef DEBUG
5
  volatile uint16_t i;
6
  for(i=0; i<5000; i++);
7
#endif
8
9
  if(ks0108Coord.x >= 128)
10
    return;
11
12
  if(ks0108Coord.x < 64) {
13
    LCD_CMD_PORT &= ~(0x01 << CSEL2);      // deselect chip 2
14
    LCD_CMD_PORT |= 0x01 << CSEL1;        // select chip 1
15
  } else if(ks0108Coord.x >= 64) {
16
    LCD_CMD_PORT &= ~(0x01 << CSEL1);      // deselect chip 1
17
    LCD_CMD_PORT |= 0x01 << CSEL2;        // select chip 2
18
  }
19
  if(ks0108Coord.x == 64)              // chip2 X-address = 0
20
    ks0108WriteCommand(LCD_SET_ADD, CHIP2);
21
  
22
  LCD_CMD_PORT |= 0x01 << D_I;          // D/I = 1
23
  LCD_CMD_PORT &= ~(0x01 << RW);          // R/W = 0
24
  LCD_DATA_DIR = 0x00;              // data port is output
25
  
26
  
27
  yOffset = ks0108Coord.y%8;
28
  if(yOffset != 0) {
29
    // first page
30
    cmdPort = LCD_CMD_PORT;            // save command port
31
    displayData = ks0108ReadData();
32
    
33
    LCD_CMD_PORT = cmdPort;            // restore command port
34
    LCD_DATA_DIR = 0x00;            // data port is output
35
    
36
    displayData |= data << yOffset;
37
    if(ks0108Inverted)
38
      displayData = ~displayData;
39
    LCD_DATA_OUT = displayData;          // write data
40
    ks0108Enable();                // enable
41
    
42
    // second page
43
    if((ks0108Coord.y+8)<64)
44
    {
45
      ks0108GotoXY(ks0108Coord.x, ks0108Coord.y+8);
46
47
      displayData = ks0108ReadData();
48
49
      LCD_CMD_PORT = cmdPort;            // restore command port
50
      LCD_DATA_DIR = 0x00;            // data port is output
51
52
      displayData |= data >> (8-yOffset);
53
      if(ks0108Inverted)
54
        displayData = ~displayData;
55
      LCD_DATA_OUT = displayData;          // write data
56
      ks0108Enable();                // enable
57
58
      ks0108GotoXY(ks0108Coord.x+1, ks0108Coord.y-8);
59
    }else
60
      ks0108GotoXY(ks0108Coord.x+1, ks0108Coord.y);
61
  } else {
62
    if(ks0108Inverted)
63
      data = ~data;
64
    LCD_DATA_OUT = data;            // write data
65
    ks0108Enable();                // enable
66
    ks0108Coord.x++;
67
  }
68
  LCD_DATA_OUT = 0x00;
69
}

MFG
Michael

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
Noch kein Account? Hier anmelden.