Forum: Mikrocontroller und Digitale Elektronik code umwandeln


von Tom (Gast)


Lesenswert?

Hallo,
ich würd euch gern mal fragen wie ihr folgende Code-Zeile ohne PGM_P und 
pgm_read_byte umschreiben würdet.

1
//load pointer to width table
2
inline PGM_P font_widthtable(FONT_P charset) 
3
{
4
  PGM_P tmp;
5
  
6
  if (sizeof(tmp) == 2)
7
    tmp = (PGM_P)pgm_read_word(&(charset.widthtable));
8
  else
9
    memcpy_P((char*)&tmp,&(charset.widthtable),sizeof(tmp));
10
  
11
  return tmp;
12
}

von budda (Gast)


Lesenswert?

so ...

1
//load pointer to width table
2
inline font_widthtable(FONT_P charset) 
3
{
4
  tmp;
5
  
6
  if (sizeof(tmp) == 2)
7
    tmp = ()pgm_read_word(&(charset.widthtable));
8
  else
9
    memcpy_P((char*)&tmp,&(charset.widthtable),sizeof(tmp));
10
  
11
  return tmp;
12
}

von Tom (Gast)


Lesenswert?

nee so geht ja schon gar nicht, weil PGM_P meines erachtens ein Zeiger 
ist oder liege ich da falsch.
Hintergrund des ganzen ist, dass der Code für einen ATMEGA geschrieben 
ist ich ihm aber für einen LPC1768  benötige es also keine pgmspace.h 
mehr gibt folglich alle damit verbundenen Variablen ersetzt werden 
müssen.

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


Lesenswert?

Tom schrieb:
> weil PGM_P meines erachtens ein Zeiger ist oder liege ich da falsch.
Wo ist das #define oder die Typdefinition dazu?

> ich würd euch gern mal fragen wie ihr folgende Code-Zeile ohne PGM_P und
> pgm_read_byte umschreiben würdet.
WELCHE der folgenden Zeilen?

von Peter (Gast)


Lesenswert?

man sollte code nicht 1:1 umschreiben, man soll verstehen was der code 
macht und dann umschreiben. Man müsste dazu wissen wo die Daten denn 
herkommen sollen die bis jetzt über pgm_read_word gelesen wurden - woher 
sollen wir das wissen?

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> man sollte code nicht 1:1 umschreiben, man soll verstehen was der code
> macht und dann umschreiben.

@TO
Da hat Peter recht.

Wenn dann noch ein bischen Wissen über typische C-Abläufe dazukommt, 
dann schreibt sich dieser Code fast von alleine. Einziges Problem: er 
hängt von genauen Aufbau der Font Strkutur ab.
Seine Aufgabe: er liefert aus diesr Fontstruktur den widthtable Pointer, 
also charset->widthtable. Mehr tut er nicht.

von Tom (Gast)


Lesenswert?

alles klar ich bin schon dabei, jedoch habe ich eine Zeile die ich nicht 
verstehe, da ich so was noch nie gesehen habe:

if(table)

also eine if-Anweisung ohne für mich ersichtliche Bedingung, ich wette 
das steckt was ganz einfaches hinter ich komme aber nicht darauf.

table ist ein Zeiger der die Adresse auf ein Array enthält

danke =)

von Peter (Gast)


Lesenswert?

in C gilt alles was !=0 == TRUE.

Also wenn der zeiger table auf etwas zeigt dann ist die bedingung war.

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:

> if(table)
>
> also eine if-Anweisung ohne für mich ersichtliche Bedingung, ich wette
> das steckt was ganz einfaches hinter

Das 'ganz einfache' besteht aus 2 Teilen

* dem if ist es schnurzegal was da in der Klammer steht. Es will
  einfach nur einen Ausdruck sehen, der ausgewertet entweder 0 ist
  oder nicht 0 ist

* auch ein Vergleich oder eine Zuweisung sind in C nichts anderes
  als Ausdrücke die einen Wert liefern

  a < b  ist ein arithmetischer Ausdruck, so wie es auch a + b ist.
  a + b liefert die Summe aus a und b, a < b liefert 0 wenn die
  Bedingung falsch ist und 1 wenn sie wahr ist.
  In C ist das hier
     d = 2 * ( a < b );
  absolut zulässig und völlig korrektes C.
  C unterscheidet nicht zwischen Bedinungen und sonstigen arithmetischen
  Ausdrücken, so das Bedingungen irgendetwas besonderes wären. Ein <
  ist genauso wie ein + oder ein * (Multiplikation) einfach nur eine
  Operation, die ihren linken Operanden mit ihrem rechten Operanden
  verwurschtet und daraus ein Ergebnis generiert, mit welchem weiter
  gerechnet werden kann.
  Wenn dieses Ergebnis (0 oder 1) dem if als Entscheidungskriterium
  vorgeworfen wird wie es weitergehen soll, dann ist das dem if recht.
  Aber das if besteht nicht darauf, dass da eine Bedingung steht. Das
  interessiert sich nur dafür ob der Ausdruck in der Klammer 0 oder
  nicht 0 ergibt, wenn man ihn auswertet.


Mit der Einführung von 'bool' in C99 haben sich die Regeln zwar ein 
bischen geändert, aber die Quintessenz bleibt immer noch die gleiche.

von Bernhard M. (boregard)


Lesenswert?

Offensichtlich wollte der Programmierer den Code flexibel halten für 
Systeme mit 2-Byte großen Zeigern und größeren Zeigern (??große und 
kleine AVRs)...
PGM_P scheint ein Zeiger zu sein.
Der Autor hofft wohl, daß der Compiler den unbenutzten if-Zweig 
rausoptimiert...

von Tom (Gast)


Lesenswert?

vielen dank bis hierher =)

ich bin nun auch schon ein bisschen weiter und versuche gerade den 
folgenden ausdruck auszuwerten:

*font_prop_24px_data + 0xFF -0x20 +1

so hinter dem font... versteckt sich ein Array welches einen Zeichensatz 
enthält nun zeigt da ein Zeiger drauf, ich habe mir schon einiges über 
Zeiger durchgelesen jedoch die oeben aufgeschriebene Notation nie 
gefunden, kennt ihr so etwas?
Ich kenn das nur wenn alles in klammern stehen würde und somit der 
Pointer verändert wird sprich das Feld auf das er zeigt ein anderes ist.

von Peter (Gast)


Lesenswert?

ich glaube du solltes erstmal dich genauer mit C beschäften. Wenn es auf 
beiden seiten ein C compiler ist, dann kannst du die anweisung doch 
einfach stehen lassen, warum willst du sie umschreiben?


a[2] == *(a+2) == 2[a]

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:

> *font_prop_24px_data + 0xFF -0x20 +1
>
> so hinter dem font... versteckt sich ein Array welches einen Zeichensatz
> enthält nun zeigt da ein Zeiger drauf, ich habe mir schon einiges über
> Zeiger durchgelesen jedoch die oeben aufgeschriebene Notation nie
> gefunden, kennt ihr so etwas?

Jeder C Programmierer kennt sowas.
Er kennt sowas, weil er weiß, dass in C

   a[d]

vom Compiler sofort umgeformt wird zu

   *(a + d)

und damit ist dann

   a[0]

identisch zu

   *( a + 0 )

und das ist wiederrum identisch zu

   *a


Eventuell solltest du erst mal deine C Kentnisse soweit 
vervollständigen, dass du zumindest das erste Drittel eines ordinären C 
Buches soweit intus hast, dass du die Dinge erkennst wenn du sie siehst.
Von dem was dann in den restlichen 2/3 des C-Buchs alles zu finden ist, 
reeden wir erst mal gar nicht.

von Tom (Gast)


Lesenswert?

ich will den teil nicht umschreiben ich will ihn verstehen ob 
*font_prop_24px_data + 0xFF - 0x20 + 1 das selbe ist wie 
*(font_prop_24px_data + 0xFF - 0x20 + 1)
sprich ob bei dieser Funktion einfach der Zeiger erhöht wird und nun auf 
ein neues element zeigt

von Peter (Gast)


Lesenswert?

Tom schrieb:
> ich will den teil nicht umschreiben ich will ihn verstehen ob
> *font_prop_24px_data + 0xFF - 0x20 + 1 das selbe ist wie
> *(font_prop_24px_data + 0xFF - 0x20 + 1)
> sprich ob bei dieser Funktion einfach der Zeiger erhöht wird und nun auf
> ein neues element zeigt

es wird nirgends etwas zugewiesen als kann auch kein Zeiger erhöht 
werden!

von Tom (Gast)


Lesenswert?

der Codeteil steht innerhalb einer Struktur  und anschließend wird die 
adresse dieses Teils einem Zeiger übergeben.

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:
> ich will den teil nicht umschreiben ich will ihn verstehen ob
> *font_prop_24px_data + 0xFF - 0x20 + 1 das selbe ist wie
> *(font_prop_24px_data + 0xFF - 0x20 + 1)

Ach komm.
Das sind doch einfache Grundlagen der Operatoren Reihenfolge (Operator 
Precedence).

Der Dereferenzier-* bindet stärker als das +

http://www.difranco.net/cop2220/op-prec.htm


Daher: Nein, das ist nicht dasselbe

von Tom (Gast)


Lesenswert?

soweit war ich auch also das es nicht das selbe sein kann.
Aber kann mir jemand auf die Sprünge helfen was dort passiert, also was 
das +0xFF-0x20+1 mit dem Zeiger anstellen.

von Peter (Gast)


Lesenswert?

Tom schrieb:
> also was das +0xFF-0x20+1 mit dem Zeiger anstellen

überhaupt nichts, es wird nur der Wert verwendet

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:
> soweit war ich auch also das es nicht das selbe sein kann.
> Aber kann mir jemand auf die Sprünge helfen was dort passiert, also was
> das +0xFF-0x20+1 mit dem Zeiger anstellen.

Du hast es immer noch nicht.
Mit dem Zeiger passiert dort überhaupt nichts mehr.

Es wird der Wert geholt, auf den der Zeiger zeigt

  *font_prop_24px_data   -> ergibt einen Wert

und mit diesem Wert wird dann weiter gerechnet

   dieser Wert + 0xFF - 0x20 + 1

wozu auch immer das gut sein soll. Die 0x20 könnten wieder mal der 
Versuch sein, seinen Code als besonders schlau zu verkaufen, indem da 
der ASCII Code eines Leerzeichens eingesetzt wird. Das ist aber nur eine 
Vermutung basierend darauf, dass es hier um Fonts geht und in 
Fonttabellen die Pixeldaten gerne erst beim ASCII-Zeichen ' ' anfangen 
um damit etwas Platz zu sparen.

von Tom (Gast)


Lesenswert?

so so so hab mir nun alles mal ganz genau angeschaut und auch verstanden 
was der Code tun soll, habe mich nun ans Umschreiben gemacht und stoße 
dabei auf folgendes Problem.
Und zwar geht es um den folgenden Abschnitt:
1
//load pointer to data table
2
inline PGM_P font_data(FONT_P charset) 
3
{
4
  PGM_P tmp;
5
  tmp = (PGM_P)pgm_read_word(&(charset->data));
6
  return tmp;
7
}

Hierbei soll aus einer Struktur der Teil data herausgelesen werden und 
die Anfangsadresse der Daten mit tmp zurückgegeben werden in der Strukur 
steht an der Stelle data folgendes :
1
char*)font_proportional_16px_data+0xFC-0x21+1

Hierbei wird der Zeiger verschoben sodass er auf dem Datenteil der Table 
von font_proportional_16pc_data steht.
So da ich ja mit einem anderen Controller arbeite habe ich den Code 
folgendermaßen verändert
1
const char* font_data(FONT_P charset) 
2
{
3
  const char* tmp;
4
  tmp = (charset.data);
5
  return tmp;
6
}

diese Funktion wird nun in einem Teil für die genaue Position des 
Zeichens in der Datentabelle benötigt
1
return (font_data(charset))+ret*font_get_height_bytes(charset);
Hierbei wird der Zeiger der Tabelle soweit verschoben bis er man 
richtigen Punkt angelangt ist. ret wird vorher erzeiugt und die 
height_bytes sind für jedes Zeichen gleich und in meinem Fall sind dies 
2.

Nun ist mein Problem, dass der Compiler in eben dieser Zeile mir 
ausgibt:
warning: return makes integer from pointer without a cast

meiner meinung nach hängt dies mit dem data zusammen weil ich ja hier 
über einen Zeiger auf eine Struktur zugreife, ich weiß aber nicht was 
falsch ist.

Wenn jemand Ahnung hat immer her damit =)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Poste vollständigen Quelltext, sonst kann Dir nicht geholfen werden.

von Tom (Gast)


Lesenswert?

naja ich dachte es ist so einfacher wenn ich das schritt für schritt 
mache dann eben so
erstmal der alte Text
1
//load pointer to data table
2
inline PGM_P font_data(FONT_P charset) 
3
{
4
  PGM_P tmp;
5
  
6
  if (sizeof(tmp) == 2)
7
    tmp = (PGM_P)pgm_read_word(&(charset->data));
8
  else
9
    memcpy_P((char*)&tmp,&(charset->data),sizeof(tmp));
10
  
11
  return tmp;
12
}
13
14
15
//load pointer to width table
16
inline PGM_P font_widthtable(FONT_P charset) 
17
{
18
  PGM_P tmp;
19
  
20
  if (sizeof(tmp) == 2)
21
    tmp = (PGM_P)pgm_read_word(&(charset->widthtable));
22
  else
23
    memcpy_P((char*)&tmp,&(charset->widthtable),sizeof(tmp));
24
  
25
  return tmp;
26
}
27
  
28
//load height of font in bytes
29
inline uint8_t font_get_height_bytes(FONT_P charset) 
30
{
31
  uint8_t t = pgm_read_byte(&charset->height);
32
   
33
  return ((t-1)/8+1);
34
}
35
36
//is additional space needed to the right of the character?
37
inline uint8_t font_get_add_space(FONT_P charset, unsigned char character) 
38
{
39
  PGM_P type = font_widthtable(charset);
40
  
41
  if ( type != 0 ) //if there is a width table, then it's a proportional font
42
    return 1;
43
  else
44
    return 0;
45
}
46
47
//get character number in charset
48
inline int16_t font_get_char_number(FONT_P charset, unsigned char character) 
49
{
50
  uint8_t first = pgm_read_byte(&charset->firstchar);
51
  uint8_t last  = pgm_read_byte(&charset->lastchar);
52
  
53
  if (character < first || character > last) return -1;
54
    else return character - first;
55
}
56
57
//get width of character
58
inline uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
59
{
60
  PGM_P table = font_widthtable(charset);
61
  
62
  if (table)
63
    return pgm_read_byte(table+font_get_char_number(charset,character));
64
  else
65
    return pgm_read_byte(&charset->width);
66
}
67
68
//find position of character in flash
69
PGM_P font_get_char_position(FONT_P charset, unsigned char character) 
70
{
71
  uint16_t ret         = 0;
72
  int16_t  charnum_ret = font_get_char_number(charset, character);
73
  uint8_t  charnum     = charnum_ret;
74
  PGM_P    base        = font_widthtable(charset);
75
76
  if (charnum_ret < 0)          //char not found
77
    return 0;
78
  
79
  if(base == 0)            //fixed width
80
    return font_data(charset) + (uint16_t)charnum * (uint8_t)(font_get_height_bytes(charset) * font_get_char_width(charset,character));
81
  
82
  if (charnum)             //proportional width
83
    while(charnum--)
84
    ret += pgm_read_byte(base++);
85
    return (font_data(charset))+ret*font_get_height_bytes(charset);
86
}
87
88
//for double-height fonts: double all bits of a upper or lower nibble
89
inline unsigned char double_bits(uint8_t part, unsigned char c) 
90
{
91
  unsigned char t = 0;
92
93
  if (part) c >>= 4;
94
  if (c & 0x08) t |= 0xC0;
95
  if (c & 0x04) t |= 0x30;
96
  if (c & 0x02) t |= 0x0C;
97
  if (c & 0x01) t |= 0x03;
98
  
99
  return t;
100
}
101
102
103
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
104
// ### lcd_draw_char(...) ###                                               
105
//
106
// Gibt ein Zeichen auf dem Display an der aktuellen Cursorposition aus
107
//
108
//   @parameter:  FONT_P charset         (gewünschter Zeichensatz; z.B. FONT_PROP_8)
109
//            uint8_t size           (gewünschte Schriftgröße; NORMAL_SIZE, DOUBLE_HEIGHT, DOUBLE_WIDTH oder DOUBLE_SIZE)
110
//            uint8_t u8_Style        (gewünschter Style; NORMAL_STYLE oder INVERTED_STYLE)
111
//            unsigned char character    (auszugebendes Zeichen)
112
// ...
113
//    @return   :  keine
114
//   
115
void lcd_draw_char(FONT_P charset, uint8_t u8_Style, unsigned char character, uint8_t u8_x_pos, uint8_t u8_y_pos, uint8_t u8_Brightness) 
116
{
117
  int8_t  i;
118
  uint8_t row = 0; //current row of char
119
  uint8_t tmp;
120
121
  //load information about character
122
  uint8_t char_width    = font_get_char_width(charset,character); 
123
  uint8_t font_height   = font_get_height_bytes(charset);
124
  PGM_P   tableposition = font_get_char_position(charset,character);
125
126
  //final size of character
127
  uint8_t char_final_height = font_height; 
128
  
129
  uint8_t u8_ColCount = 0;
130
131
   //write chracter
132
  do 
133
  {
134
    for( i = (row) ; i < char_width * font_height ; i += font_height) 
135
    {
136
        
137
      if (character != 0x20)
138
      {
139
        tmp = pgm_read_byte(tableposition+i);
140
      }
141
      else
142
      {
143
        tmp = 0;
144
      }
145
      
146
      // Ausgabefenster setzen
147
      lcd_set_window( (u8_x_pos + u8_ColCount) , (u8_x_pos + u8_ColCount) ,u8_y_pos+(8*row),u8_y_pos+8+(8*row));
148
149
      lcd_send_byte(CMD, 0x2C);      
150
151
      for (uint8_t u8_col = 0 ; u8_col <= 7 ; u8_col++)
152
      {
153
        if (u8_Style == NORMAL_STYLE)
154
        {
155
          if (tmp & _BV(u8_col))
156
          {
157
            lcd_send_byte(PARA, u8_Brightness);
158
            lcd_send_byte(PARA, u8_Brightness);
159
          }
160
          else
161
          {
162
            lcd_send_byte(PARA, 0x00);
163
            lcd_send_byte(PARA, 0x00);
164
          }
165
        }
166
        else
167
        {
168
          // -> Invertierte Darstellung
169
          if (!(tmp & _BV(u8_col)))
170
          {
171
            lcd_send_byte(PARA, u8_Brightness);
172
            lcd_send_byte(PARA, u8_Brightness);
173
          }
174
          else
175
          {
176
            lcd_send_byte(PARA, 0x00);
177
            lcd_send_byte(PARA, 0x00);
178
          }
179
        }
180
      }
181
182
      u8_ColCount++;      
183
184
    }
185
186
    u8_ColCount = 0;
187
  } 
188
  while (++row < char_final_height);
189
190
}

und hier in der neuen Variante wo aber wie gesagt etwas nciht stimmt 
beim font_data undfont_widthtable
1
//  FUNKTIONEN (Textausgabe)
2
// --------------------------
3
4
//load pointer to data table
5
const char* font_data(FONT_P charset) 
6
{
7
  const char* tmp;
8
  tmp = (charset.data);
9
  return tmp;
10
}
11
12
13
//load pointer to width table
14
const char* font_widthtable(FONT_P charset) 
15
{
16
  const char* tmp;
17
  tmp =(charset.widthtable);
18
  return tmp;
19
}
20
  
21
//load height of font in bytes
22
uint8_t font_get_height_bytes(FONT_P charset) 
23
{
24
  uint8_t t = (charset.height);
25
   
26
  return ((t-1)/8+1);
27
}
28
29
//is additional space needed to the right of the character?
30
uint8_t font_get_add_space(FONT_P charset, unsigned char character) 
31
{
32
  const char* type = font_widthtable(charset);
33
  
34
  if ( type != 0 ) //if there is a width table, then it's a proportional font
35
    return 1;
36
  else
37
    return 0;
38
}
39
40
//get character number in charset
41
inline int16_t font_get_char_number(FONT_P charset, unsigned char character) 
42
{
43
  uint8_t first = charset.firstchar;
44
  uint8_t last  = charset.lastchar;
45
  
46
  if (character < first || character > last) return -1;
47
    else return (character - first);
48
}
49
50
//get width of character
51
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
52
{
53
  const char* table = font_widthtable(charset);
54
  
55
  if (table)
56
    return (table+font_get_char_number(charset,character));
57
  else
58
    return (charset.width);
59
}
60
61
//find position of character in flash
62
char* font_get_char_position(FONT_P charset, unsigned char character) 
63
{
64
  uint16_t      ret         = 0;
65
  int16_t       charnum_ret = font_get_char_number(charset, character);
66
  uint8_t       charnum     = charnum_ret;
67
  const char*   base        = font_widthtable(charset);
68
69
  if (charnum_ret < 0)          //char not found
70
    return 0;
71
  
72
  if(base == 0)            //fixed width
73
    return font_data(charset) + (uint16_t)charnum * (uint8_t)(font_get_height_bytes(charset) * font_get_char_width(charset,character));
74
  
75
  if (charnum)             //proportional width
76
    while(charnum--)
77
    ret += (base++);
78
    return (font_data(charset))+ret*font_get_height_bytes(charset);
79
}
80
81
//for double-height fonts: double all bits of a upper or lower nibble
82
inline unsigned char double_bits(uint8_t part, unsigned char c) 
83
{
84
  unsigned char t = 0;
85
86
  if (part) c >>= 4;
87
  if (c & 0x08) t |= 0xC0;
88
  if (c & 0x04) t |= 0x30;
89
  if (c & 0x02) t |= 0x0C;
90
  if (c & 0x01) t |= 0x03;
91
  
92
  return t;
93
}
94
95
96
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
97
// ### lcd_draw_char(...) ###                                               
98
//
99
// Gibt ein Zeichen auf dem Display an der aktuellen Cursorposition aus
100
//
101
//   @parameter:  FONT_P charset         (gewünschter Zeichensatz; z.B. FONT_PROP_8)
102
//            uint8_t size           (gewünschte Schriftgröße; NORMAL_SIZE, DOUBLE_HEIGHT, DOUBLE_WIDTH oder DOUBLE_SIZE)
103
//            uint8_t u8_Style        (gewünschter Style; NORMAL_STYLE oder INVERTED_STYLE)
104
//            unsigned char character    (auszugebendes Zeichen)
105
// ...
106
//    @return   :  keine
107
//   
108
void lcd_draw_char(FONT_P charset, uint8_t u8_Style, unsigned char character, uint8_t u8_x_pos, uint8_t u8_y_pos, uint8_t u8_Brightness) 
109
{
110
  int8_t  i;
111
  uint8_t row = 0; //current row of char
112
  uint8_t tmp;
113
114
  //load information about character
115
  uint8_t char_width    = font_get_char_width(charset,character); 
116
  uint8_t font_height   = font_get_height_bytes(charset);
117
  char*   tableposition = font_get_char_position(charset,character);
118
119
  //final size of character
120
  uint8_t char_final_height = font_height; 
121
  
122
  uint8_t u8_ColCount = 0;
123
124
   //write chracter
125
  do 
126
  {
127
    for( i = (row) ; i < char_width * font_height ; i += font_height) 
128
    {
129
        
130
      if (character != 0x20)
131
      {
132
        tmp = (tableposition+i);
133
      }
134
      else
135
      {
136
        tmp = 0;
137
      }
138
      
139
      // Ausgabefenster setzen
140
      lcd_set_window( (u8_x_pos + u8_ColCount) , (u8_x_pos + u8_ColCount) ,u8_y_pos+(8*row),u8_y_pos+8+(8*row));
141
142
      lcd_send_byte(CMD, 0x2C);      
143
144
      for (uint8_t u8_col = 0 ; u8_col <= 7 ; u8_col++)
145
      {
146
        if (u8_Style == NORMAL_STYLE)
147
        {
148
          if (tmp & (1<<(u8_col)))
149
          {
150
            lcd_send_byte(PARA, u8_Brightness);
151
            lcd_send_byte(PARA, u8_Brightness);
152
          }
153
          else
154
          {
155
            lcd_send_byte(PARA, 0x00);
156
            lcd_send_byte(PARA, 0x00);
157
          }
158
        }
159
        else
160
        {
161
          // -> Invertierte Darstellung
162
          if (!(tmp & (1<<(u8_col))))
163
          {
164
            lcd_send_byte(PARA, u8_Brightness);
165
            lcd_send_byte(PARA, u8_Brightness);
166
          }
167
          else
168
          {
169
            lcd_send_byte(PARA, 0x00);
170
            lcd_send_byte(PARA, 0x00);
171
          }
172
        }
173
      }
174
175
      u8_ColCount++;      
176
177
    }
178
179
    u8_ColCount = 0;
180
  } 
181
  while (++row < char_final_height);
182
183
}

von Tom (Gast)


Lesenswert?

hier nocheinmal die Strutkur
1
struct font_info {
2
    uint16_t size;                  //size of data array
3
    uint8_t  width;                 //(maximum) width of character
4
    uint8_t  height;                //height of character
5
    uint8_t  firstchar;             //the number of the first included character (often 0x20)
6
    uint8_t  lastchar;              //the last included character (often 0xFF)
7
    const char* widthtable;    //Pointer to the table holding character widths (NULL for monospaced fonts)
8
    const char* data;          //Pointer to data arrray
9
    };
10
typedef const struct font_info FONT_P;

von Tom (Gast)


Lesenswert?

okay so ein ganzer Code ist auch doof zu lesen
mal in kurz:
seh ich das richtig

tmp = (PGM_P)pgm_read_word(&(charset->data)); charset->data =pointer

ist das gleiche wie

tmp = charset.data

wobei sich hinter charset.data ein pointer verbirgt und der Rückgabewert 
der Funktion hier auf ein Pointer ist.

von Karl H. (kbuchegg)


Lesenswert?

Was um alles in der Welt hast du blos aus dem Originalcode gemacht.

<Kopfschüttel>

von Tom (Gast)


Lesenswert?

ich habe ihn mir angesehen und ihn auch verstanden was wie wo hin muss 
mir fehlt leider das fahcwissen darüber wie ich z.B. das Array aus der 
Struktur auslese und einen Zeiger auf das erste Feld lege.
ich erhalte mitlerweile von meinem Compiler auch keine warnungen mehr 
jedoch funktioniert das einlesen der Tabelle meiner meinung nach nicht.

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:

> typedef const struct font_info FONT_P;

Das ist Unsinn.
FONT_P war im Originalcode gedacht als Datentyp für einen Pointer. 
Dieser Pointer auf eine Font Struktur wurde an Funktionen 
weitergereicht, damit die dann Einzelinformationen aus der Struktur auf 
die sie einen Pointer erhalten haben herausholen können.

Verkompliziert wurde das im Original dadurch, dass es sich um keinen 
SRAM Pointer handelte, sondern das der Pointer auf Daten im Flash 
zeigte. Dadurch war es nicht mehr einfach möglich zu sagen

    charset->width

um an die Breite eines Zeichens zu kommen, wie man das normalerweise 
machen würde, sondern man musste den Umweg über die pgm_.... Funktionen 
gehen.

Aber: Die Funktionen sollen nach wie vor einen Pointer auf die 
Fontstuktur bekommen! Du willst doch nicht ständig Strukturen komplett 
umkopieren!
1
typedef const struct font_info * FONT_P;
2
3
4
//load pointer to data table
5
const char* font_data(FONT_P charset) 
6
{
7
  return charset->data;
8
}
9
10
11
//load pointer to width table
12
const char* font_widthtable(FONT_P charset) 
13
{
14
  return charset->widthtable;
15
}
16
  
17
//load height of font in bytes
18
uint8_t font_get_height_bytes(FONT_P charset) 
19
{
20
  uint8_t t = charset->height;
21
  return ((t-1)/8+1);
22
}
23
24
//is additional space needed to the right of the character?
25
uint8_t font_get_add_space(FONT_P charset, unsigned char character) 
26
{
27
  const char* type = font_widthtable(charset);
28
  
29
  if ( type != 0 ) //if there is a width table, then it's a proportional font
30
    return 1;
31
  else
32
    return 0;
33
}
34
35
//get character number in charset
36
inline int16_t font_get_char_number(FONT_P charset, unsigned char character) 
37
{
38
  uint8_t first = charset->firstchar;
39
  uint8_t last  = charset->lastchar;
40
  
41
  if (character < first || character > last) return -1;
42
    else return (character - first);
43
}
44
45
//get width of character
46
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
47
{
48
  const char* table = font_widthtable(charset);
49
  
50
  if (table)
51
    return table+font_get_char_number(charset,character);
52
  else
53
    return charset->width;
54
}
55
56
//find position of character in flash
57
char* font_get_char_position(FONT_P charset, unsigned char character) 
58
{
59
  uint16_t      ret         = 0;
60
  int16_t       charnum_ret = font_get_char_number(charset, character);
61
  uint8_t       charnum     = charnum_ret;
62
  const char*   base        = font_widthtable(charset);
63
64
  if (charnum_ret < 0)          //char not found
65
    return 0;
66
  
67
  if(base == 0)            //fixed width
68
    return font_data(charset) +
69
           (uint16_t)charnum * (uint8_t)(font_get_height_bytes(charset) * font_get_char_width(charset,character));
70
  
71
  if (charnum)             //proportional width
72
    while(charnum--)
73
      ret += *base++;
74
75
  return font_data(charset) + ret*font_get_height_bytes(charset);
76
}
77
78
//for double-height fonts: double all bits of a upper or lower nibble
79
inline unsigned char double_bits(uint8_t part, unsigned char c) 
80
{
81
  unsigned char t = 0;
82
83
  if (part) c >>= 4;
84
  if (c & 0x08) t |= 0xC0;
85
  if (c & 0x04) t |= 0x30;
86
  if (c & 0x02) t |= 0x0C;
87
  if (c & 0x01) t |= 0x03;
88
  
89
  return t;
90
}
91
92
93
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94
// ### lcd_draw_char(...) ###                                               
95
//
96
// Gibt ein Zeichen auf dem Display an der aktuellen Cursorposition aus
97
//
98
//   @parameter:  FONT_P charset         (gewünschter Zeichensatz; z.B. FONT_PROP_8)
99
//            uint8_t size           (gewünschte Schriftgröße; NORMAL_SIZE, DOUBLE_HEIGHT, DOUBLE_WIDTH oder DOUBLE_SIZE)
100
//            uint8_t u8_Style        (gewünschter Style; NORMAL_STYLE oder INVERTED_STYLE)
101
//            unsigned char character    (auszugebendes Zeichen)
102
// ...
103
//    @return   :  keine
104
//   
105
void lcd_draw_char(FONT_P charset, uint8_t u8_Style, unsigned char character, uint8_t u8_x_pos, uint8_t u8_y_pos, uint8_t u8_Brightness) 
106
{
107
  int8_t  i;
108
  uint8_t row = 0; //current row of char
109
  uint8_t tmp;
110
111
  //load information about character
112
  uint8_t char_width    = font_get_char_width(charset,character); 
113
  uint8_t font_height   = font_get_height_bytes(charset);
114
  char*   tableposition = font_get_char_position(charset,character);
115
116
  //final size of character
117
  uint8_t char_final_height = font_height; 
118
  
119
  uint8_t u8_ColCount = 0;
120
121
   //write chracter
122
  do 
123
  {
124
    for( i = (row) ; i < char_width * font_height ; i += font_height) 
125
    {
126
        
127
      if (character != 0x20)
128
      {
129
        tmp = tableposition[i];
130
      }
131
      else
132
      {
133
        tmp = 0;
134
      }
135
      
136
      // Ausgabefenster setzen
137
      lcd_set_window( (u8_x_pos + u8_ColCount) , (u8_x_pos + u8_ColCount) ,u8_y_pos+(8*row),u8_y_pos+8+(8*row));
138
139
      lcd_send_byte(CMD, 0x2C);      
140
141
      for (uint8_t u8_col = 0 ; u8_col <= 7 ; u8_col++)
142
      {
143
        if (u8_Style == NORMAL_STYLE)
144
        {
145
          if (tmp & (1<<(u8_col)))
146
          {
147
            lcd_send_byte(PARA, u8_Brightness);
148
            lcd_send_byte(PARA, u8_Brightness);
149
          }
150
          else
151
          {
152
            lcd_send_byte(PARA, 0x00);
153
            lcd_send_byte(PARA, 0x00);
154
          }
155
        }
156
        else
157
        {
158
          // -> Invertierte Darstellung
159
          if (!(tmp & (1<<(u8_col))))
160
          {
161
            lcd_send_byte(PARA, u8_Brightness);
162
            lcd_send_byte(PARA, u8_Brightness);
163
          }
164
          else
165
          {
166
            lcd_send_byte(PARA, 0x00);
167
            lcd_send_byte(PARA, 0x00);
168
          }
169
        }
170
      }
171
172
      u8_ColCount++;      
173
174
    }
175
176
    u8_ColCount = 0;
177
  } 
178
  while (++row < char_final_height);
179
180
}

Da ich das hier nicht testen kann, bin ich nicht sicher ob das jetzt so 
stimmt, aber soweit dürfte ich nicht daneben liegen

von Karl H. (kbuchegg)


Lesenswert?

Warte noch, da sind noch Fehler


Edit:
Ich denke, ich hab jetzt die meisten Fehler, die du beim Ausbau der 
Flash-Zugriffe gemacht hast im vorhergehenden Code korrgiert.

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:
> ich habe ihn mir angesehen und ihn auch verstanden was wie wo hin muss
> mir fehlt leider das fahcwissen darüber wie ich z.B. das Array aus der
> Struktur auslese und einen Zeiger auf das erste Feld lege.
> ich erhalte mitlerweile von meinem Compiler auch keine warnungen mehr
> jedoch funktioniert das einlesen der Tabelle meiner meinung nach nicht.

Wenn du Datenstrukturen nicht verstehst, dann mal sie dir auf einen 
Zettel auf! Die Technik funktioniert perfekt um sich einen Überblick zu 
verschaffen, wie eine Datenstruktur aufgebaut ist und wie sie benutzt 
werden will.
Aber einfach so nach Gutdünken in einer Datenstruktur herumfuhrwerken 
führt nur zu Fehlern.

von Tom (Gast)


Lesenswert?

so ich habe das mal eingebunden und in folgenden zeilen
1
return (font_data(charset) + (uint16_t)charnum * (uint8_t)(font_get_height_bytes(charset) * font_get_char_width(charset,character)));
2
3
...
4
5
  return (font_data(charset) + ret*font_get_height_bytes(charset));

noch die Warnung

assignment makes integer from pointer without a cast

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die Funktion font_data liefert als Rückgabewert einen Pointer.

von Karl H. (kbuchegg)


Lesenswert?

Die erste derartige Warnung kommt hier
1
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
2
{
3
  const char* table = font_widthtable(charset);
4
  
5
  if (table)
6
    return table+font_get_char_number(charset,character);
7
  else
8
    return charset->width;
9
}

und es muss lauten
1
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
2
{
3
  const char* table = font_widthtable(charset);
4
  
5
  if (table)
6
    return table[font_get_char_number(charset,character)];
7
  else
8
    return charset->width;
9
}

von Karl H. (kbuchegg)


Lesenswert?

Die von dir gezeigten Zeilen bringen die Warnung

 warning: return discards qualifiers from pointer target type

und die Lösung sollte offensichtlich sein, wenn man sich mal den 
Datentyp ansieht, den der Ausdruck beim return generiert und mit dem 
Datentyp des Rückgabewertes der Funktion vergleicht.

von Tom (Gast)


Lesenswert?

bist du dir da sicher?
ich geh ind er Funktion an die richtige Stelle in dem Datenarray wo 
meine Breite verzeichnet ist und table zeigt auf die erste Zeile und 
font_get_char_number(charset,character) sagt mir wieviele ich 
weiterrutschen muss.

hab da noch ne frage zu deiner änderung von tmp = tableposition+i
zu
tmp = tableposition[i]

an dieser stelle wird meiner meinung nach die position der Datentabelle 
verändert, dann ergibt für mich tableposition[i] keinen sinn

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:
> bist du dir da sicher?

Ja
Bin ich

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:

> an dieser stelle wird meiner meinung nach die position der Datentabelle
> verändert, dann ergibt für mich tableposition[i] keinen sinn

Du hast

    return pgm_read_byte(table+font_get_char_number(charset,character));

zu

    return table+font_get_char_number(charset,character);

übersetzt.
Das ist aber falsch.


Ein

   i = pgm_read_byte( a );

wird zu einem

   i = *a;

denn genau das macht pgm_read_byte. Das Byte holen, welches an der 
Adresse a im Speicher sitzt.

Wenn also im Original das Byte geholt wird, welches vom Tabellenanfang x 
Zeichen entfernt ist

   pgm_rad_byte( table + x );

dann ist das in Nicht-Flash-Schreibweise ganz einfach

   table[x]

Das pgm_read_byte beinhaltet eine implizte Dereferenzierung! Und

  *(table+x)
ist nun mal identisch zu
  table[x]


Du hast bei deiner Übersetzung an manchen Stellen einfach das 
pgm_read_byte unter den Tisch fallen lassen. Das darfst du aber nicht! 
Wenn schon, dann hättest du es mit einem Derferenzier-* ersetzen müssen. 
Und daraus ergeben sich dann natürlich an anderen Stellen Möglichkeiten 
für Vereinfachungen.
Aus
  return pgm_read_byte( &charset->width );
wird dann
  return * &charset->width;

und da die Dereferenzierung eines Ausdrucks von dem man die Adresse 
nimmt, der Ausdruck selber ist, vereinfacht das dann zu

  return charset->width;

Hier ist nicht nur das pgm_read_byte weggefallen sondern auch das &. 
Dies deshalb weil *& eine 0-Operation ist. Nur dort wo du keinen 
Adressoperator im pgm_read_byte hast, kannst du nicht einfach nur das 
pgm_read_byte weglassen, sondern du musst tatsächlich den langen Weg 
gehen und pgm_read_byte durch einen * ersetzten und dann nachehen ob du 
etwas vereinfachen kannst.

von Tom (Gast)


Lesenswert?

okay danke, kann mir noch jemand sagen wie ich den Rückgabewert 
(Pointer) anpassen kann bzw so mache,dass er verarbeitet werden kann

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:
> okay danke, kann mir noch jemand sagen wie ich den Rückgabewert
> (Pointer) anpassen kann bzw so mache,dass er verarbeitet werden kann


Der Ausdruck beim Return hat welchen Datentyp?

Die Funktion hat welchen Datentyp in ihrer Vereinbarung des 
Returnwertes?


Daraus folgt dann das weitere Vorgehen.

von Tom (Gast)


Lesenswert?

also ich muss nen zeiger zurückgeben und habe zur verarbeitung einen 
zeiger plus einem Wert

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:
> also ich muss nen zeiger zurückgeben

Du hast nicht einfach nur einen Zeiger.

Auch Zeiger haben Datentypen!
Nämlich den Datentyp des Objektes auf welches sie zeigen!

Ein Zeiger der auf einen int zeigt, ist datentypmässig nicht dasselbe 
wie ein Zeiger der auf einen double zeigt! Auch wenn beides Zeiger sind.

> und habe zur verarbeitung einen
> zeiger plus einem Wert

Also: welche Datentypen hast du?

von Karl H. (kbuchegg)


Lesenswert?

Beim return hast du

  return (font_data(charset) + ret*font_get_height_bytes(charset));


  font_data(charset)
ist ein Ausdruck, genauer ein Funktionsaufruf. Welchen Datentyp liefert 
diese Funktion zurück?

von Tom (Gast)


Lesenswert?

also meine drei hinteren werte sind vom typ int und die Rückgabe der 
Funktion ist const char

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:
> also meine drei hinteren werte sind vom typ int

?
Welche 3 hinteren Werte

> und die Rückgabe der
> Funktion ist const char

?

Hier ist die Funktion

const char* font_data(FONT_P charset)
{
 ...
}


ihr Rückgabetype ist  'const char*'
also ein Pointer auf einen Character und diese Character ist als 
konstant anzusehen, kann also nicht verändert werden.


Damit hast du


 return (font_data(charset) + ret*font_get_height_bytes(charset));
         |                |
         |                |

       Der Teil hier hat den
       Datentyp   const char*


Die Addition zu einem Pointer ergibt wieder einen Pointer (genauso ist 
in C letzten Endes der Arrayzugriff definiert) wobei sich der Datentyp 
des Pointers nicht ändert.
D.h. dieser komplette Ausdruck

     font_data(charset) + ret*font_get_height_bytes(charset));

hat immer noch den Datentyp 'const char*'

und die Funktion in der dieser return steht, sagt von sich selber, das 
sie was zurückliefert?

char* font_get_char_position(FONT_P charset, unsigned char character)
{


Die Funktion liefert einen 'char*'

Ein 'const char*' ist aber nicht dasselbe wie ein 'char*'

von Tom (Gast)


Lesenswert?

hm okay alles klar das leuchtet mir alles ein =) Danke
das Programm läuft aber leider immer noch nicht auch jetzt ohne 
Warnungen und Fehler ... hm

von Tom (Gast)


Lesenswert?

so hab mich mal an die "Fehlersuche" gemacht und zwar mittels LEDs die 
angehen sollen wenn das Programm an bestimmten Punkten angelangt ist.

der erste Punkt des Programmes ist font_get_char_width
1
struct font_info {
2
    uint16_t size;                  //size of data array
3
    uint8_t  width;                 //(maximum) width of character
4
    uint8_t  height;                //height of character
5
    uint8_t  firstchar;             //the number of the first included character (often 0x20)
6
    uint8_t  lastchar;              //the last included character (often 0xFF)
7
    const char* widthtable;    //Pointer to the table holding character widths (NULL for monospaced fonts)
8
    const char* data;          //Pointer to data arrray
9
    };
10
11
#ifdef FONTS_INCLUDE_font_vw_24px
12
  extern  const struct font_info font_vw_24px;
13
  #define FONT_VW_24 &font_vw_24px
14
#endif
15
16
const struct font_info font_vw_24px = {0x80+(0x17<<8),0x15,0x18,0x20,0xFF,font_vw_24px_data,(char*)(font_vw_24px_data+0xFF-0x20+1)};
17
18
//get width of character
19
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
20
{ LPC_GPIO2->FIODIR |= 0x01; // LED1
21
  const char* table = font_widthtable(charset);
22
  LPC_GPIO2->FIODIR |= 0x04; // LED3
23
  if (table)
24
  { 
25
    return (table[font_get_char_number(charset,character)]);
26
  }
27
28
//*table+font_get_char_number(charset,character);
29
  else
30
  {
31
    return (charset->width);
32
  }
33
}
34
35
//load pointer to width table
36
const char* font_widthtable(FONT_P charset) 
37
{  LPC_GPIO2->FIODIR |= 0x02; // LED2
38
  return charset->widthtable;
39
}

hierbei geht die erste LED an, die zweite geht im  font_widthtable geht 
auch an und die dritte hinter der Funktion bleibt jedoch aus ...

von Tom (Gast)


Lesenswert?

hinter der struktur fehlt noch
1
typedef const struct font_info * FONT_P;

von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:

> hierbei geht die erste LED an, die zweite geht im  font_widthtable geht
> auch an und die dritte hinter der Funktion bleibt jedoch aus ...

wie rufst du das ganze auf?
Ist der charset Pointer, der da überall reingegeben wird korrekt?

von Tom (Gast)


Lesenswert?

über lcd_draw_char(font_vw_24px, NORMAL_STYLE,'-',30, 70, 255);

mittlerweile durchläuft er das ganze programm auch und zeigt mir was an 
es sieht den zeichen auch ähnlich jedoch sind ein paar pixel falsch 
angeordnet, sprich irgendwas beim auslesen passt so nicht ganz

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.