Forum: Mikrocontroller und Digitale Elektronik Problem mit pgm_read_byte


von rhood (Gast)


Lesenswert?

Hallo!
Ich habe hier eine 5*7 Fonttabelle und eine 16*12 Font Tabelle
und diese haben folgende struktur
1
const uint8_t __Font5x7[] PROGMEM = {
2
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// (space)
3
4
...
5
tFont Font5x7 = {(PGM_P)__Font5x7, 7, 8, 7, 1, 0};
1
const uint8_t __Font12x16[] PROGMEM = {
2
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "(space)"
3
  0x7C, 0x00, 0xFF, 0x33, 0xFF, 0x33, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "!"
4
5
...
6
tFont Font12x16 = {(PGM_P)__Font12x16, 11, 16, 22, 2, 0};

diese müssen über eine funktion putstr auf dem display DOGS102 zu sehen 
sein, nun für die kleiensc hriftart funktioniert es, aber weshalb auch 
immer gehts beim großen font nicht

hier die vorgegebene font struktur:
1
typedef struct
2
{
3
  PGM_P font;
4
  unsigned char Width;
5
  unsigned char Height;
6
  unsigned char CharSize;
7
  unsigned char Lines;
8
  unsigned char Prop;
9
} tFont;
1
void DOGS102_PutStr(unsigned char PosX, unsigned char Line, char * pdata, tFont font)
2
{
3
  unsigned int Len = 0;
4
  unsigned char Data = 0;
5
  unsigned char l;
6
  unsigned char FontIndex;
7
  unsigned char ZeroLine;
8
9
  while (*pdata)
10
  {
11
    unsigned char w;
12
    FontIndex = 0;
13
    for (w = 0; w < font.Width; w++)
14
    {
15
      ZeroLine = 0;
16
      for (l = 0; l < font.Lines; l++)
17
      {
18
        Data = pgm_read_byte(&font.font[(*pdata-Font_AsciiOffset)*(font.CharSize)+(w+1)*(l+1)-1]);// PROBLEM LIEGT HIER
19
        FontIndex++;
20
        ZeroLine |= Data;
21
        LCDCache[(DOGS102_PIXELX * (Line + l)) + PosX + Len] = Data;
22
      }
23
      Len++;
24
      if (ZeroLine == 0 && w > 1 && font.Prop == 0)
25
      break;
26
      
27
      // falls ein Zeichen genau font.Width Bytes benoetigt, dann am Ende noch
28
      // eine Leerspalte einfuegen
29
      if (w == font.Width - 1)
30
      {
31
        Data = 0x00;
32
        
33
        for (l = 0; l < font.Lines; l++)
34
        LCDCache[(DOGS102_PIXELX * Line) + PosX + Len] = Data;
35
        Len++;
36
      }
37
    }
38
    pdata++;
39
  }
40
  
41
  // write all lines needed for the font
42
  for (l = 0; l < font.Lines; l++)
43
  {
44
    WriteCache(PosX, Line + l, Len);
45
  }
46
}

format_ascii_font ist ascii wert vom space

kann mir vllt jemand da weiterhelfen?

von Karl H. (kbuchegg)


Lesenswert?

Der Teil hier
1
   .... (w+1)*(l+1)-1
ist unlogisch.

Da Arrays in C beginnend mit 0 indiziert werden und das ganze im Grunde 
ein 2-dimensionales Array abbildet, wäre
1
   .... w * font.Lines + l
wesentlich logischer
Eventuell auch
1
   .... w * l * font.width
je nachdem in welcher Reihenfolge die Bytes in den Font Pixeldaten 
angeordnet sind.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

rhood schrieb:
> aber weshalb auch immer gehts beim großen font nicht
WAS "geht" denn "nicht"?
Wie äussert sich der Fehler?

von Masl (Gast)


Lesenswert?

Lass das pgm_read Gedöns und nimm __flash. Das ergibt einfacheren und 
übersichtlicheren Code.

von Karl H. (kbuchegg)


Lesenswert?

Masl schrieb:
> Lass das pgm_read Gedöns und nimm __flash. Das ergibt einfacheren und
> übersichtlicheren Code.

Ist in dem Fall ziemlich egal.
Ob er mit __flash falsch in den Speicher indiziert oder ob er die 
Speicheradresse für pgm_read_byte falsch ausrechnet, schenkt sich 
nichts. Es ist in der gleichen Weise falsch.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

Die Variante hier

> ein 2-dimensionales Array abbildet, wäre
>
1
>    .... w * font.Lines + l
2
>

ist aufgrund

>   0x7C, 0x00, 0xFF, 0x33, 0xFF, 0x33, 0x7C, 0x00,
>   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "!"

die richtige. Die beiden Bytes, die senkrecht aneinander gelegt das 
Zeichen ergeben, folgen offenbar unmittelbar hintereinander.

d.h das ist
1
O = Byte oben
2
U = Byte unten
3
4
                 O   U   O   U   O   U   O   U ...
5
                7C  00  FF  33  FF  33  7C  00 ...
6
7
Pixelspalte      1   1   2   2   3   3   4   4 ....

Um also an die Bytes der x-ten Pixelspalte zu kommen, muss man die 
Spaltennummer mit der Anzahl der Bytes pro Spalte multiplizeren. Die 
einzelnen Bytes jeder Spalte folgen dann direkt hintereinander.
Font.Lines ist genau diese Anzahl an Bytes
w ist die Nummer der jeweils auszugebenden Pixelspalte.

Daher
1
    for (w = 0; w < font.Width; w++)
2
    {
3
      for (l = 0; l < font.Lines; l++)
4
      {
5
        gib das Byte mit den Pixeln von
6
          Pixeldaten_des_Zeichen[ w * Font.Lines + l ]
7
        aus.
8
      }
9
    }

: Bearbeitet durch User
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.