Forum: Mikrocontroller und Digitale Elektronik C -> Zeichen aus Font suchen / rechnen?!


von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Ist in der Funktion ein Denkfehler?
Die Zeichen die dabei raus kommen sind verschoben oder überhaupt nicht 
zu erkennen. Ist bei meiner Berechnung etwas falsch?
Kann sich das mal bitte jemand anschauen?!
1
/*  Wird benoetigt um Fontparameter zu berechnen
2
*/
3
static inline Font_t GetPixelStart(uint8_t c, Font_t Font, const uint8_t __flash *ptrFont)
4
{
5
  #define OFFSET_SETTING_INFOS  8
6
  
7
  uint8_t charNum = 0;
8
  
9
  Font.uiCharWidth  = ptrFont[(c-Font.ptrFont[FONT_FIRST_CHAR])+OFFSET_SETTING_INFOS]; // Breite des Zeichens
10
  Font.uiIndexBegin  = Font.ptrFont[FONT_PIXEL_BEGIN]; // Offset (ab hier beginnen die Pixel Daten)
11
  
12
  if ( Font.ptrFont[FONT_FIXED_OR_VARIABLE] == 1 ) // Fonts mit fester Breite
13
  {
14
    for(  ; charNum <= (c - Font.ptrFont[FONT_FIRST_CHAR])-1 ; charNum++)
15
    {
16
      Font.uiIndexBegin += (Font.ptrFont[FONT_WIDTH] * ((Font.ptrFont[FONT_HEIGHT] / 8)+1)); // Font breite berechnen
17
    }
18
  }
19
  else if ( Font.ptrFont[FONT_FIXED_OR_VARIABLE] == 0)
20
  {
21
    for(  ; charNum <= (c - Font.ptrFont[FONT_FIRST_CHAR])-1 ; charNum++)
22
    {
23
      Font.uiIndexBegin += (ptrFont[charNum + OFFSET_SETTING_INFOS] * 2 );
24
    }
25
  }
26
  
27
  return Font;
28
}

P.S
Anbei mal ein Beispiel Font.

Mfg

von Stefan F. (Gast)


Lesenswert?

Ohne den vollständigen Quelltext ist das schwer zu sagen. Die Werte der 
allermeisten Konstanten sind unbekannt und man muss raten, wie du die 
Funktion verwendest.

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
> Ohne den vollständigen Quelltext ist das schwer zu sagen. Die
> Werte der
> allermeisten Konstanten sind unbekannt und man muss raten, wie du die
> Funktion verwendest.
Da hast Du vollkommend recht. Habe noch was vergessen..
1
enum Font_Struct
2
{
3
  FONT_BEGIN,
4
  FONT_END,
5
  FONT_WIDTH,
6
  FONT_HEIGHT,
7
  FONT_FIRST_CHAR,
8
  FONT_CHAR_COUNT
9
  FONT_BEGIN_PIXEL,
10
  FONT_FIXED_OR_VARIABLE,
11
};

Das sind eigentlich nur die Indexnummern für die Werte aus dem "Font 
Array".
Die Funktion rufe ich auch, bevor ich ein Zeichen brauche, in der 
Struktur die zurückgegeben wird, sollte dann der Start der Pixel 
Informationen und deren einzelnen Breiten stehen..

von Stefan F. (Gast)


Lesenswert?

Wie rufst du die Funktion auf?

Annahme:
Font ist ein zunächst leeres Objekt, dass die Funktion befüllen soll.
ptrFont ist ein Zeiger auf die Font Daten im Header.

Das passt aber nicht zu deinem Code, denn da liest du munter 
wechselweise von ptrFont und Font.ptrFont. Frage: Wo sind die Font Daten 
(input). In ptrFont oder in Font.ptrFont?

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
> Wie rufst du die Funktion auf?
>
> Annahme:
> Font ist ein zunächst leeres Objekt, dass die Funktion befüllen soll.
> ptrFont ist ein Zeiger auf die Font Daten im Header.
>
> Das passt aber nicht zu deinem Code, denn da liest du munter
> wechselweise von ptrFont und Font. Frage: Wo sind die Font Daten
> (input). In ptrFont oder in Font?

Stimmt. Sehe ich gerade.

Jan H. schrieb:
> Font.uiCharWidth  =
> ptrFont[(c-Font.ptrFont[FONT_FIRST_CHAR])+OFFSET_SETTING_INFOS]; //
> Breite des Zeichens
>   Font.uiIndexBegin  = Font.ptrFont[FONT_PIXEL_BEGIN]; // Offset (ab
> hier beginnen die Pixel Daten)
Du meinst mit Sicherheit das? Ist ein wenig sinnlos, muss ich ändern. 
Jedoch ist beides eine Referenz auf den Zeichensatz.

von Stefan F. (Gast)


Lesenswert?

Jan H. schrieb:
> Du meinst mit Sicherheit das?

Ja genau, das.

Du kannst das Ganze ja mal in einem Debugger oder Simulator durchsteppen 
und dabei schauen, ob die Berechnungen die erwarteten Werte ergeben. 
Oder du gibst sie zum Debugging auf einem seriellen Port aus.

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
> Jan H. schrieb:
>> Du meinst mit Sicherheit das?
>
> Ja genau, das.
>
> Du kannst das Ganze ja mal in einem Debugger oder Simulator durchsteppen
> und dabei schauen, ob die Berechnungen die erwarteten Werte ergeben.
> Oder du gibst sie zum Debugging auf einem seriellen Port aus.

Habe es angepasst.
1
static inline Font_t GetPixelStart(uint8_t c, Font_t Font, const uint8_t __flash *ptrFont)
2
{
3
  #define OFFSET_SETTING_INFOS  8
4
  
5
  uint8_t charNum = 0;
6
  
7
  Font.uiCharWidth  = ptrFont[ ( c - Font.ptrFont[_FONT_FIRST_CHAR] ) + OFFSET_SETTING_INFOS ]; // Breite des Zeichens
8
  Font.uiIndexBegin  = ptrFont[_FONT_PIXEL_BEGIN]; // Offset (ab hier beginnen die Pixel Daten)
9
  
10
  if ( Font.ptrFont[_FONT_FIXED_OR_VARIABLE] == 1 ) // Fonts mit fester Breite
11
  {
12
    for(  ; charNum <= ( c - Font.ptrFont[_FONT_FIRST_CHAR] ) - 1 ; charNum++ )
13
    {
14
      Font.uiIndexBegin += ( Font.ptrFont[_FONT_WIDTH] * ( ( Font.ptrFont[_FONT_HEIGHT] / 8 ) + 1 ) ); // Font breite berechnen
15
    }
16
  }
17
  else if ( Font.ptrFont[_FONT_FIXED_OR_VARIABLE] == 0)
18
  {
19
    for(  ; charNum <= ( c - Font.ptrFont[_FONT_FIRST_CHAR] ) - 1 ; charNum++ )
20
    {
21
      Font.uiIndexBegin += (ptrFont[charNum + OFFSET_SETTING_INFOS] * 2 ); // Anstatt *2 schieben wir hier einfach
22
    }
23
  }
24
  
25
  return Font;
26
}

von Stefan F. (Gast)


Lesenswert?

Jan H. schrieb:
> Habe es angepasst.

Und?

von holger (Gast)


Lesenswert?

>Ist in der Funktion ein Denkfehler?
>Die Zeichen die dabei raus kommen sind verschoben oder überhaupt nicht
>zu erkennen. Ist bei meiner Berechnung etwas falsch?

Ja, deine Berechnung ist falsch. Bei deiner Berechnung der Bytes
pro Zeichen kommt immer der gleiche Wert raus. Die Anzahl der Bytes
pro Zeichen ist aber nicht immer gleich. Du wirst schon die Werte
unter  // char widths auswerten müssen statt Font.ptrFont[FONT_WIDTH].

von holger (Gast)


Lesenswert?

Ach vergiss meinen Post. Hatte mir den unteren Teil nicht angesehen;)

von Jan H. (janiiix3)


Lesenswert?

holger schrieb:
> Ach vergiss meinen Post. Hatte mir den unteren Teil nicht angesehen;)

Wollte schon sagen.. :D

von holger (Gast)


Lesenswert?

Neuer Versuch:

Font.uiIndexBegin += (ptrFont[charNum + OFFSET_SETTING_INFOS] * 2 )

Die 2 da hinten. Für den Courier müsste da eine 4 stehen.
Du berücksichtigst die Höhe des Fonts dort nicht.

von Jan H. (janiiix3)


Lesenswert?

holger schrieb:
> Neuer Versuch:
>
> Font.uiIndexBegin += (ptrFont[charNum + OFFSET_SETTING_INFOS] * 2 )
>
> Die 2 da hinten. Für den Courier müsste da eine 4 stehen.
> Du berücksichtigst die Höhe des Fonts dort nicht.
Es geht da wirklich nur um die Weite des Zeichens. Die Höhe ist ja Fix.

von holger (Gast)


Lesenswert?

>Es geht da wirklich nur um die Weite des Zeichens. Die Höhe ist ja Fix.

Ja, klar ist die fix. Aber mit der zwei hinten kannst du nur Zeichen
von 9 bis 16 Pixel Höhe auswerten. Die Höhe ist aber 26Pixel.

von Jan H. (janiiix3)


Lesenswert?

holger schrieb:
>>Es geht da wirklich nur um die Weite des Zeichens. Die Höhe ist ja Fix.
>
> Ja, klar ist die fix. Aber mit der zwei hinten kannst du nur Zeichen
> von 9 bis 16 Pixel Höhe auswerten. Die Höhe ist aber 26Pixel.
Habs mit "*4" versucht, genau das gleiche.

von Chris (Gast)


Lesenswert?

Du lieferst nicht gerade gute Informationen um Dir zu helfen, ist Dir 
das klar?


* Dein "enum Font_Struct" enthält andere Werte als Du im Code benutzt 
(z.B. FONT_BEGIN_PIXEL vs. _FONT_PIXEL_BEGIN)

* Auch in Deinem "angepassten" Code geht weiterhin ptrFont und 
Font.ptrFont munter durcheinander.


Weißt Du eigentlich, wie die Font-Daten organisiert sind?
Anhand des Zeichens 33 (das Ausrufungszeichen) habe ich durch 
ausprobieren herausbekommen, dass die Daten wohl spaltenweise von oben 
nach unten abgelegt sind, das lsb der Bytes ist dabei oben. 
Spaltenwechsel ist immer an einer Bytegrenze, d.h. beim vorliegenden 
Font sind die höherwertigsten 6 Bits jedes vierten Byte "don't care".

Nehmen wir mal an:
1
#define _FONT_WIDTH             2
2
#define _FONT_HEIGHT            3
3
#define _FONT_FIRST_CHAR        4
4
#define _FONT_PIXEL_BEGIN       6
5
#define _FONT_FIXED_OR_VARIABLE 7

Anzahl Bytes pro Spalte ist also:
1
 bytes_per_col = (((ptrFont[_FONT_HEIGHT]-1) / 8) + 1);

Für den Offset musst Du alle Zeichenbreiten vor dem gesuchten addieren.
1
 
2
Font.uiIndexBegin = ptrFont[_FONT_PIXEL_BEGIN];
3
for( charNum=0 ; charNum < (c - ptrFont[_FONT_FIRST_CHAR]) ; charNum++)
4
  Font.uiIndexBegin += (ptrFont[charNum + OFFSET_SETTING_INFOS] * bytes_per_col );

Bist Du sicher, dass Du die Pixeldaten dann auch richtig ausgegeben 
bekommst, wenn Dir die Routine den Offset richtig berechnet hat? (ich 
hab' da so meine Zweifel... ;-)

von W.S. (Gast)


Lesenswert?

Jan H. schrieb:
> Habe es angepasst.

..und es ist nach wie vor zumindest für mich herzlich unleserlich. Was 
willst du mit diesem Code eigentlich bezwecken? Was bedeutet 
"GetPixelStart" und wozu sollte man sowas brauchen?


Also, ich sehe das GANZ anders:

Für ne grafische Darstellung braucht man eine Funktion, die ein 
Textzeichen an einer bestimmten Stelle auf einer grafischen Oberfläche 
(z.B. Display) zeichnen kann. Im Allgemeinen sollte dies in einer Farbe 
möglich sein, die irgendwo vorgegeben ist. Dazu kommt, daß das 
Textzeichen in einem gewünschten Font gezeichnet werden soll. Für das 
Zeichnen von Zeichenketten (Strings) ist es wünschenswert, daß diese 
Funktion die Breite des aktuellen Zeichens zurückliefert. Also sieht so 
eine Funktion erstmal etwa so aus:
1
int ZeichneChar(char c, int x, int y, irgendwas* Font, int Farbe)
2
{...
Und diese Funktion soll mit den verschiedensten Fonts zurecht kommen, 
also müssen die Fonts eine gewisse Struktur haben, aus der man möglichst 
leicht ermitteln kann, was da alles an Zeichen vorhanden ist, wie groß 
so ein Zeichen ist, wo der zugehörige Glyph steht und so weiter.
Ich habe das bei meinen Fonts so gehandhabt:
1
/*  Beschreibung des verwendeten Font-Formates:
2
 zuerst kommt der Font-Header in folgendem Format: */
3
4
#define Fontheadersize 6
5
struct Fontheader
6
{ byte Capitals; /* Hoehe der Grossbuchstaben */
7
  byte Height;   /* Font-Gesamthoehe */
8
  byte Ascent;   /* Hoehe ueber Null-Linie */
9
  byte Descent;  /* Tiefe unter Null-Linie */
10
  char ChMin;    /* kleinstes vorhandenes Zeichen */
11
  char ChMax;    /* groesstes vorhandenes Zeichen */
12
};
13
14
/* danach kommen unterschiedlich viele Char-Entries.
15
   eigentlich ist 'Disp' ein 16 bit Offset, aber der
16
   Font muss bei BigEndian und LittleEndian-CPU's
17
   gleichermassen funktionieren, deswegen die explizite
18
   Aufteilung in DispHi und DispLo  */
19
20
#define Charentrysize 4
21
struct CharEntry
22
{ byte DispHi;   /* Hi vom Displacement ab Fontbeginn */
23
  byte DispLo;   /* Lo vom Displacement ab Fontbeginn */
24
  byte dX;       /* Breite in Pixeln */
25
  byte dY;       /* Hoehe in Pixeln */
26
};
27
28
/* danach kommen die Pixel. Jeder CharEntry (s.o.) zeigt
29
   auf den Beginn des zu seinem Char gehörigen Bitmusters.
30
   Jedes Bitmuster beginnt an einem ganzen Byte, aber innerhalb
31
   geht es je nach Zeichenbreite asynchron zu den Bytegrenzen */

Und die Funktion, die mithilfe eines so aufgebauten Fonts Text auf die 
Glotze schreiben kann geht so (hier für Monochrom):
1
/***************************************************************
2
 Zeichnet das Textzeichen im aktuellen Font an der
3
 angegebenen Stelle und liefert die Breite des Zeichens
4
 ***************************************************************/
5
int CgCh_at(int X, int Y, char Ch, const char* Font, int mode)
6
{ struct Fontheader* FHE;
7
  struct CharEntry*  CHE;
8
  byte*  Pix;
9
  long   top, bott;
10
  dword  w;
11
  dword  pixw;
12
  long   dX;
13
14
  top   = Y;
15
16
/* aus dem Font die Breite, Höhe und Pixel entnehmen */
17
  FHE = (struct Fontheader*) Font;
18
  if ((Ch < FHE->ChMin)||(Ch > FHE->ChMax)) Ch = 0;
19
  else Ch = Ch - FHE->ChMin;
20
  CHE = (struct CharEntry*) ((long) FHE + Fontheadersize);
21
  CHE += Ch;
22
  w   = (CHE->DispHi << 8) | CHE->DispLo;
23
  Pix = (byte*) ((long) FHE + w);
24
25
/* bott setzen */
26
  bott = top + CHE->dY;
27
  if (bott>lcdhoehe-1) bott = lcdhoehe-1;
28
29
/* die Register sind jetzt:
30
  bott = zeigt jetzt hinter die unterste zu schreibende Zeile des Zeichens
31
  Pix  = Zeiger auf zugehörige Pixel im Font
32
  FHE, CHE haben sich (fast) erledigt
33
  Nun die ersten Fontpixel und die Maske laden
34
 */
35
  pixw = *Pix++;
36
  w = 1;
37
38
/* Y - Zeichen-Zyklus */
39
  while (top < bott)
40
  {   /* X - Zeichen-Zyklus */
41
      dX  = 0;
42
      while (dX < CHE->dX)   /* Zeichenbreite in Pixeln */
43
      { if (pixw & w) CgPixel_at (X+dX, top, mode);
44
  ++dX;
45
        w = (w << 1) & 0xFF;
46
        if (!w)
47
        {   pixw = *Pix++;
48
            w = 1;
49
  }
50
      }
51
      ++top;
52
  }
53
  return CHE->dX;
54
}

So geht das - und so ein Font ist von hause aus proportional, hat also 
je nach Zeichen unterschiedliche Zeichenbreiten. Natürlich kann man 
damit auch Courier12 machen, indem man die Zeichenbreite eben beim 
Fontmachen konstant läßt. Ebenso kann man damit auch monochrome Icons 
und Piktogramme machen, die Schreibfunktion kommt mit allen Formaten 
zurecht, solange der Font korrekt ist.

Den ganzen Krempel hatte ich hier schon mal gepostet, ebenso dazu einen 
kleinen Font-Compiler.

W.S.

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Nachtrag: damit du dir das besser vorstellen kannst.

W.S.

von Jan H. (janiiix3)


Lesenswert?

Erstmal danke euch beiden für die super Erklärung.

Wenn ich den Index richtig berechnet haben sollte, bin ich bis jetzt 
soweit mit der Ausgabefunktion.

Ich vermute mal das es hier auch noch einige Sachen gibt die fehlerhaft 
sind.
1
void Ssd1306PutChar( char c , int16_t y , int16_t x )
2
{  
3
  Font = calcFontStart( c , Font , Font.ptrFont );  
4
  
5
  /* Höhe des Zeichens in "Pages" aufgeteilt ( Page = 8 Pixel )
6
  */
7
  uint8_t uiPages = ( ( Font.ptrFont[3] / 8 ) + 1);
8
  
9
  uint16_t uiLastWidth = 0;
10
  
11
  for ( uint8_t uiActualPage = 0 ; uiActualPage < uiPages ; uiActualPage++ )
12
  {
13
    for ( uint8_t uiActualWidth = 0 ; uiActualWidth < Font.uiCharWidth ; uiActualWidth++ )
14
    {
15
      for ( uint8_t uiPixel = 0 ; uiPixel < 8 ; uiPixel++ )
16
      {
17
        if ( Font.ptrFont[Font.uiIndexBegin + ( uiLastWidth + uiActualWidth ) ] & 1<<uiPixel )
18
        {
19
          if ( uiActualPage == 0 )
20
          {
21
            Ssd1306DrawPixel( ( y + uiPixel ) , ( x + uiActualWidth ) );
22
          }else
23
          {
24
            Ssd1306DrawPixel( ( y + uiPixel ) + ( uiActualPage * 128 ) , ( x + uiActualWidth ) + ( uiActualPage * 128 ) );            
25
          }
26
        }else
27
        {
28
          if ( uiActualPage == 0 )
29
          {
30
            Ssd1306ClearPixel( ( y + uiPixel ) , ( x + uiActualWidth ) );
31
          }else
32
          {
33
            Ssd1306ClearPixel( ( y + uiPixel ) + ( uiActualPage * 128 ) , ( x + uiActualWidth ) + ( uiActualPage * 128 ) );
34
          }
35
        }        
36
      }
37
    }uiLastWidth+=Font.uiCharWidth;
38
  }
39
}

von Stefan F. (Gast)


Lesenswert?

Ich würde hier nicht einzelne Pixel ausgeben, sondern möglichst größere 
Blöcke von Bytes. Sonst dauert das ja "ewig". Kannst du nicht direkt in 
den Pufferspeicher schreiben, anstatt den Umweg über Ssd1306DrawPixel() 
zu nehmen?

von leo (Gast)


Lesenswert?

W.S. schrieb:
> int ZeichneChar(char c, int x, int y, irgendwas* Font, int Farbe)
> {...

Kaum. Im allgemeinen will man nicht bei jedem Zeichen Font oder Farbe 
wechseln.
Das Interface stimmt nicht. Font und Farbe stellt man einmal für 
zukünftige Ausgaben ein.

leo

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
> Ich würde hier nicht einzelne Pixel ausgeben, sondern möglichst größere
> Blöcke von Bytes. Sonst dauert das ja "ewig". Kannst du nicht direkt in
> den Pufferspeicher schreiben, anstatt den Umweg über Ssd1306DrawPixel()
> zu nehmen?

Klar kann man das. Wollte aber auch mal die Pixel Variante versuchen und 
verstehen.

Habe es ja vorher so gehabt.

von Stefan F. (Gast)


Lesenswert?

Jan H. schrieb:
> Wollte aber auch mal die Pixel Variante versuchen und verstehen.

Bei mir sind die Bytes im Font genau so ausgerichtet, wie im Speicher 
des Display (Jedes Byte stellt 8 Pixel dar, die untereinander stehen, 
also ein vertikale Linie ergeben). Wenn die Zeile Text "zufällig" genau 
passend ausgerichtet ist, kann ich einfach die Bytes aus dem Font 1:1 in 
den Pufferspeicher übertragen. Wenn nicht, teile ich den Text in obere 
und untere Hälfte auf, bevor ich die beiden halben Zeilen in den 
Pufferspeicher übertrage.

Aber die Sache mit dem Aufteilen hätte ich mir schenken können. Da bin 
ich übers Ziel hinaus geschossen (von wegen Eierlegende Wollmilchsau). 
In der Praxis genügt es, acht Zeilen mit fester y-Position zu haben. Wer 
will schon Text dazwischen ausgeben?

von Jan H. (janiiix3)


Lesenswert?

Habe jetzt die Routine für das suchen der Pixeldaten erneuert.
1
Font_t GetFont( uint8_t c )
2
{
3
  Font_t Font;
4
  
5
  Font.uiWidht       = 0;
6
  Font.uiHeight       = GetFontHeight( _ptrFont );
7
  uint8_t  uiHeightInBytes = ( Font.uiHeight + 7 ) / 8; /* calculates height in rounded up bytes */
8
9
  uint8_t uiFirstChar = _ptrFont[ _FONT_FIRST_CHAR ];
10
  uint8_t uiCharCount = _ptrFont[ _FONT_CHAR_COUNT ];
11
12
  Font.uiIndex = 0;
13
  
14
  c -= uiFirstChar;
15
16
  if ( IsFixedWidthFont( _ptrFont ) ) 
17
  {
18
    Font.uiWidht = _ptrFont[ _FONT_FIXED_WIDTH ];
19
    Font.uiIndex = ( c * uiHeightInBytes * Font.uiWidht + _FONT_WIDTH_TABLE );
20
  }else 
21
  {
22
23
    for (uint8_t i = 0; i < c; i++) 
24
    {
25
      Font.uiIndex += _ptrFont[ _FONT_WIDTH_TABLE + i ];
26
    }
27
28
    Font.uiIndex = ( Font.uiIndex * uiHeightInBytes + uiCharCount + _FONT_WIDTH_TABLE );
29
30
    Font.uiWidht = _ptrFont[ _FONT_WIDTH_TABLE + c ];
31
  }
32
  
33
  return Font;
34
}
Damit bekomme ich jetzt definitiv den richtigen Anfang meines gesuchten 
Zeichens, des Weiteren scheibe ich die ganzen Informationen wie ( Höhe, 
Breite , Start ) in eine Struktur.

Der Zeiger zu dem Array, ist jetzt nicht mehr Teil der Struktur. Der 
Zeiger wurde global ausgelagert.

Wenn das mit dem Zeichen der einzelnen Pixel sauber klappt, werde ich 
deine Lösung auch vorziehen. Wie Du schon sagtest, frisst das um längen 
nicht so viele Ressourcen.

Was kann ich an der Ausgabefunktion noch verändern / verbessern?
Diese soll die Pixel in ein "VRAM" schreiben, dass später an einer 
anderen Stelle, wenn es fertig befüllt ist, übertragen werden.

Zeichen in den VRAM schreiben ->
1
void Ssd1306PutChar( char c , int16_t y , int16_t x )
2
{  
3
  Font = GetFont( c );
4
  
5
  /* Höhe des Zeichens in "Pages" aufgeteilt ( Page = 8 Pixel )
6
  */
7
  uint8_t uiPages = ( ( _ptrFont[3] / 8 ) + 1);
8
  
9
  uint16_t uiLastWidth = 0;
10
  
11
  for ( uint8_t uiActualPage = 0 ; uiActualPage < uiPages ; uiActualPage++ )
12
  {
13
    for ( uint8_t uiActualWidth = 0 ; uiActualWidth < Font.uiWidht ; uiActualWidth++ )
14
    {
15
      for ( uint8_t uiPixel = 0 ; uiPixel < 8 ; uiPixel++ )
16
      {
17
        if ( _ptrFont[Font.uiIndex + ( uiLastWidth + uiActualWidth ) ] & 1<<uiPixel )
18
        {
19
          if ( uiActualPage == 0 )
20
          {
21
            Ssd1306DrawPixel( ( y + uiPixel ) , ( x + uiActualWidth ) );
22
          }else
23
          {
24
            Ssd1306DrawPixel( ( y + uiPixel ) + ( uiActualPage * 128 ) , ( x + uiActualWidth ) + ( uiActualPage * 128 ) );            
25
          }
26
        }else
27
        {
28
          if ( uiActualPage == 0 )
29
          {
30
            Ssd1306ClearPixel( ( y + uiPixel ) , ( x + uiActualWidth ) );
31
          }else
32
          {
33
            Ssd1306ClearPixel( ( y + uiPixel ) + ( uiActualPage * 128 ) , ( x + uiActualWidth ) + ( uiActualPage * 128 ) );
34
          }
35
        }        
36
      }
37
    }uiLastWidth+=Font.uiWidht;
38
  }
39
}

Pixel verarbeiten und an richtige Stelle in den VRAM malen ->
1
void Ssd1306DrawPixel( int16_t x , int16_t y )
2
{
3
   DisplayRam[ y + ( x / 8 ) * SSD1306_LCD_Width ] |=  ( 1 << ( x & 7 ) );
4
}

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.