Forum: Mikrocontroller und Digitale Elektronik Font für gelb/blaue OLED SSD1306 gesucht


von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

Moin!

Ich suche einen passenden Font für die Displays, die oben gelb und unten 
blau sind. Da ich einen 32 Bitter nutze sind die bestehenden als 16 Bit 
Werte hinterlegt, 8 Bit nützt mir also leider wenig, das wäre zu viel 
Tipparbeit.

Problem beim bestehenden ist, dass bei manchen Buchstaben g,j, etc unten 
ein paar Pixel blau sind. Da die Hersteller sicher für mich keine extra 
gelben Zeilen einfügen bleibt nur der Font Wechsel.

Hat da vielleicht jemand einen? 11x18 sollte es aber sein, für den 
drunter braucht man schon ne Lupe.

von foobar (Gast)


Lesenswert?

Rockbox (OS-Firmware für MP3-Player) hat nen Fontpack mit Fonts u.a. für 
solche Displays.

von u8g2 (Gast)


Lesenswert?

u8g2 hat viele fonts

von Tim (Gast)


Lesenswert?

Wie viele Pixel misst denn der gelbe Rand? Das wäre vielleicht die 
wichtigste Info.

von Christian J. (Gast)


Lesenswert?

u8g2 schrieb:
> u8g2 hat viele fonts

Ja, da habe ich auch schon dran gedacht, die habe ich im Arduino 
irgendwo gesehen.

Ok, ich dachte jemand hätte das zufällig schon mal gehabt. Der gelbe 
Rand misst 10 Pixel glaube ich. Genau weiss ich das nicht.

von Ron (Gast)


Lesenswert?

Kannst ja mal fotografieren, vergrößern und auszählen. Die Gesamthöhe 
ist 32 oder 64?

von Stefan F. (Gast)


Lesenswert?

Christian J. schrieb:
> Genau weiss ich das nicht.

Das solltest du wohl erstmal heraus finden.

von Johannes S. (Gast)


Lesenswert?

Christian J. schrieb:
 Da ich einen 32 Bitter nutze sind die bestehenden als 16 Bit
> Werte hinterlegt

das verstehe ich nicht, was hat die Wortbreite des Prozessors mit den 
Fonts zu tun? Ob ein Font als Bit-, Byte oder 16/32 Bit breites Wort 
abgelegt ist, das interessiert doch nur die Routine die Zeichen vom 
Fontspeicher in den Grafikspeicher überträgt. Und da gibt es viele 
verschiedene Formate und Speichermöglichkeiten.
Und ich habe eine Fontdefinition auch noch nie abgetippt, vorhandene 
kann man kopieren oder lässt einen Fontgenerator das include erzeugen.

Ein guter Ansatz ist in der Adafruit GFX Library, da können alternativ 
zu den fixed size auch custom fonts benutzt werden. Da werden GNU Free 
Type Fonts genutzt, von denen es jede Menge gibt.

https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts
Ein Generator wird mitgeliefert, es gibt aber auch einen netten Online 
Generator:
http://oleddisplay.squix.ch/#/home

Diese Fonts sollten aber in einem Buffer generiert werden und dann am 
Stück zum Display geschickt werden. Kostet etwas mehr Speicher, sollte 
für deine 32 Bitter aber kein Problem sein.

von Christian J. (Gast)


Lesenswert?

Johannes S. schrieb:
> Ein Generator wird mitgeliefert, es gibt aber auch einen netten Online
> Generator:
> http://oleddisplay.squix.ch/#/home

Das ist ja ein nettes Teil! Da muss ich aber meine Pixelroutine 
umschreiben. Ist ein anderes Prinzip. Und halt etwas mehr Denkarbeit..

von W.S. (Gast)


Lesenswert?

Johannes S. schrieb:
> das verstehe ich nicht, was hat die Wortbreite des Prozessors mit den
> Fonts zu tun?

Er ist zu bequem, jedesmal 0x hinzuschreiben, das will er auf die Hälfte 
reduzieren.

Abgesehen davon gibt es hier im Forum bereits ausreichend an Software 
dafür, so daß man sich das manuelle Schreiben der Glyphen als Quelltext 
ersparen kann. Siehe z.B. FM.EXE

W.S.

von Johannes S. (Gast)


Lesenswert?

Christian J. schrieb:
> Da muss ich aber meine Pixelroutine
> umschreiben.

Wenn man die Adafruit GFX nicht komplett nutzen will, dann kann man den 
Part mit dem Zeichen Ausgeben schon rausoperieren, das hat nicht viele 
Abhängigkeiten.
Die Lib ist C++, Vorteile sind das diese damit für viele verschiedene 
Displays incl. LED Matrizen verwendet werden kann und auch mehrere 
Displays sind einfach mehrere Instanzen.

von Christian J. (Gast)


Lesenswert?

Johannes S. schrieb:
> das verstehe ich nicht, was hat die Wortbreite des Prozessors mit den
> Fonts zu tun? Ob ein Font als Bit-, Byte oder 16/32 Bit breites Wort
> abgelegt ist, das interessiert doch nur die Routine die Zeichen vom
> Fontspeicher in den Grafikspeicher überträgt.

Jojo,

kläre mich doch mal auf. Dieser Font Generator erzeugt ja allerhand 
kryptisches Zeugs.

Meine Lösung, irgendwo abgeschrieben: Die Fonts werden stur pixelweise 
kodiert, pfeif auf Platz, davon habe ich 512kb. Die Routine zieht sich 
Breite unf Höhe und liest einfach soviel Bytes, wie ein Buchstabe hat.

Bei diesem Generator aber steckt mehr Hirnschmalz drin, da wird wohl 
optimiert und damit wird das Ganze komplizierter. Ich nutze weder 
Arduino, noch irgendwas aus diesem Universum, auch kein C++, nur die 
Standard C Libs.

Mehr ist das nicht. Schaue ich mir eben die GFX Ada LIb an sprengt der 
Source Code ja schon alle Grenzen.....
1
/
2
//  Draw 1 char to the screen buffer
3
//  ch      => Character to write
4
//  Font    => Font to use
5
//  color   => Black or White
6
//
7
char ssd1306_WriteChar(char ch, FontDef Font, SSD1306_COLOR color)
8
{
9
    uint32_t i, b, j;
10
11
    // Check remaining space on current line
12
    if (SSD1306_WIDTH <= (SSD1306.CurrentX + Font.FontWidth) ||
13
            SSD1306_HEIGHT <= (SSD1306.CurrentY + Font.FontHeight))
14
        // Not enough space on current line
15
        return 0;
16
17
    // Translate font to screenbuffer
18
    for (i = 0; i < Font.FontHeight; i++) {
19
        b = Font.data[(ch - 32) * Font.FontHeight + i];
20
        for (j = 0; j < Font.FontWidth; j++)  {
21
            if ((b << j) & 0x8000)
22
                ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color);
23
            else
24
                ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR)!color);
25
        }
26
    }
27
28
    // The current space is now taken
29
    SSD1306.CurrentX += Font.FontWidth;
30
31
    // Return written char for validation
32
    return ch;
33
}

von Christian J. (Gast)


Lesenswert?

Na gut, das kriegen wir noch hin... ich muss ja nicht jede Zeile 
verstehen, dieses PROGMEM gibt es nicht. Hauptsache es funktioniert....
1
// Draw a character
2
/**************************************************************************/
3
/*!
4
   @brief   Draw a single character
5
    @param    x   Bottom left corner x coordinate
6
    @param    y   Bottom left corner y coordinate
7
    @param    c   The 8-bit font-indexed character (likely ascii)
8
    @param    color 16-bit 5-6-5 Color to draw chraracter with
9
    @param    bg 16-bit 5-6-5 Color to fill background with (if same as color,
10
   no background)
11
    @param    size_x  Font magnification level in X-axis, 1 is 'original' size
12
    @param    size_y  Font magnification level in Y-axis, 1 is 'original' size
13
*/
14
/**************************************************************************/
15
void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
16
                            uint16_t color, uint16_t bg, uint8_t size_x,
17
                            uint8_t size_y) {
18
19
  if (!gfxFont) { // 'Classic' built-in font
20
21
    if ((x >= _width) ||              // Clip right
22
        (y >= _height) ||             // Clip bottom
23
        ((x + 6 * size_x - 1) < 0) || // Clip left
24
        ((y + 8 * size_y - 1) < 0))   // Clip top
25
      return;
26
27
    if (!_cp437 && (c >= 176))
28
      c++; // Handle 'classic' charset behavior
29
30
    startWrite();
31
    for (int8_t i = 0; i < 5; i++) { // Char bitmap = 5 columns
32
      uint8_t line = pgm_read_byte(&font[c * 5 + i]);
33
      for (int8_t j = 0; j < 8; j++, line >>= 1) {
34
        if (line & 1) {
35
          if (size_x == 1 && size_y == 1)
36
            writePixel(x + i, y + j, color);
37
          else
38
            writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y,
39
                          color);
40
        } else if (bg != color) {
41
          if (size_x == 1 && size_y == 1)
42
            writePixel(x + i, y + j, bg);
43
          else
44
            writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg);
45
        }
46
      }
47
    }
48
    if (bg != color) { // If opaque, draw vertical line for last column
49
      if (size_x == 1 && size_y == 1)
50
        writeFastVLine(x + 5, y, 8, bg);
51
      else
52
        writeFillRect(x + 5 * size_x, y, size_x, 8 * size_y, bg);
53
    }
54
    endWrite();

von Johannes S. (Gast)


Lesenswert?

das PROGMEM ist für die Kompatibilität mit AVR und dem getrennten 
Adressraum für RAM und Flash, kann man per define als nichts wegmachen.

Die Fonts können Ligaturen und die Zeichen sind nicht alle gleich breit, 
damit die Beschreibung eines Zeichens aufwändiger. Das macht eben das 
Löschen eines Zeichens schwieriger, man kann keine Dummyfläche löschen 
bzw. muss Wissen wie groß das Zeichen war das da Stand. Und durch die 
Ligaturen (übergreifende Zeichen) kann man das vorhergehende Zeichen 
teilweise kaputtschreiben.
Deshalb ist einfacher in einen Buffer zu rendern und den dann am Block 
an das Display zu schicken. Was bei den OLED mit SSD1306 und seinen max. 
1 kB ja nicht weh tut. Adafruit unterstützt das mit den 'Canvas', also 
eine Leinwand auf die erst gemalt wird und diese wird dann übertragen. 
Das kann auch ein Teilausschnitt wie der gelbe Bereich im Display sein.

ein paar defines die man häufig braucht um AVR/Arduino portabel zu 
machen:
1
#ifndef PROGMEM
2
 #define PROGMEM
3
#endif
4
#ifndef boolean
5
 #define boolean bool
6
#endif
7
#ifndef bitRead
8
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
9
#endif
10
#ifndef bitSet
11
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
12
#endif
13
#ifndef bitClear
14
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
15
#endif
16
#ifndef bitWrite
17
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
18
#endif
19
#ifndef pgm_read_byte
20
 #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
21
#endif

und startWrite() / endWrite() ist eine Optimierung die man hier auch 
weglassen kann wenn man in einen Buffer rendert.

von Johannes S. (Gast)


Lesenswert?

Christian J. schrieb:
> if (!gfxFont) { // 'Classic' built-in font

das ist allerdings noch die einfache Zeichenroutine für die groben 
Fonts, für die Free Type ist es noch etwas aufwändiger.

von W.S. (Gast)


Lesenswert?

Christian J. schrieb:
1
 void Adafruit_GFX::drawChar
2
   (int16_t x, 
3
    int16_t y, 
4
    unsigned char c,
5
    uint16_t color, 
6
    uint16_t bg, 
7
    uint8_t size_x,
8
    uint8_t size_y)

Grr..igitt. Viel zu viele Parameter für ein Grafik-Charout. Eigentlich 
wären hier nur die ersten 3 Parameter erforderlich, der Rest sollte zum 
Teil im Font stecken (size_x und size_y) und zum anderen Teil in einem 
Grafik-Device-Kontext (Textcolor und Background-Color).

W.S.

von Johannes S. (Gast)


Lesenswert?

W.S. schrieb:
> Grr..igitt. Viel zu viele Parameter für ein Grafik-Charout.

tja, wenn man Quelltext nicht lesen kann und sogar die Kommentare 
ignoriert. Gründe warum ich niemals Quelltext von dir benutzen werde, 
andere haben es einfach wesentlich besser drauf.

PS:
in der einfachen Form reicht sogar ein 'uint8_t c' als Argument für 
write() und damit eine Streamausgabe direkt auf das Display arbeiten.

PSS:
backcolor und forecolor sind auch etwas tricky: wenn gleich, dann ist 
der Hintergrund transparent (wird nicht gezeichnet). Das sieht man nicht 
sofort weil das default ist und die Zeichen dann erstmal übereinander 
liegen. Wenn die Zeichen den Hintergrund löschen sollen, dann muss den 
entsprechend setzen.

von Hugo H. (hugo_hu)


Lesenswert?

Christian J. schrieb:
> Ich suche einen passenden Font für die Displays, die oben gelb und unten
> blau sind. Da ich einen 32 Bitter nutze sind die bestehenden als 16 Bit
> Werte hinterlegt, 8 Bit nützt mir also leider wenig, das wäre zu viel
> Tipparbeit

Warum kaufst Du Dir so etwas?

von Ron (Gast)


Lesenswert?

Also, wenn es so eines ist, dann sind die ersten 16 (von 64) Zeilen 
gelb:
https://www.buydisplay.com/media/catalog/product/cache/8d4d2075b1a30681853bef5bdc41b164/y/e/yellow-blue_0.96_inch_oled_display_breakout_board_library_for_arduino_1.jpg
Hätte mich auch gewundert, wenn es irgendeine krumme (!=2^n) Zahl 
gewesen wäre.

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.