mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik code umwandeln


Autor: Tom (Gast)
Datum:

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

//load pointer to width table
inline PGM_P font_widthtable(FONT_P charset) 
{
  PGM_P tmp;
  
  if (sizeof(tmp) == 2)
    tmp = (PGM_P)pgm_read_word(&(charset.widthtable));
  else
    memcpy_P((char*)&tmp,&(charset.widthtable),sizeof(tmp));
  
  return tmp;
}

Autor: budda (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so ...

//load pointer to width table
inline font_widthtable(FONT_P charset) 
{
  tmp;
  
  if (sizeof(tmp) == 2)
    tmp = ()pgm_read_word(&(charset.widthtable));
  else
    memcpy_P((char*)&tmp,&(charset.widthtable),sizeof(tmp));
  
  return tmp;
}

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 =)

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in C gilt alles was !=0 == TRUE.

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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]

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Tom (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

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

überhaupt nichts, es wird nur der Wert verwendet

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
//load pointer to data table
inline PGM_P font_data(FONT_P charset) 
{
  PGM_P tmp;
  tmp = (PGM_P)pgm_read_word(&(charset->data));
  return tmp;
}

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 :
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
const char* font_data(FONT_P charset) 
{
  const char* tmp;
  tmp = (charset.data);
  return tmp;
}

diese Funktion wird nun in einem Teil für die genaue Position des 
Zeichens in der Datentabelle benötigt
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 =)

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

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

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja ich dachte es ist so einfacher wenn ich das schritt für schritt 
mache dann eben so
erstmal der alte Text
//load pointer to data table
inline PGM_P font_data(FONT_P charset) 
{
  PGM_P tmp;
  
  if (sizeof(tmp) == 2)
    tmp = (PGM_P)pgm_read_word(&(charset->data));
  else
    memcpy_P((char*)&tmp,&(charset->data),sizeof(tmp));
  
  return tmp;
}


//load pointer to width table
inline PGM_P font_widthtable(FONT_P charset) 
{
  PGM_P tmp;
  
  if (sizeof(tmp) == 2)
    tmp = (PGM_P)pgm_read_word(&(charset->widthtable));
  else
    memcpy_P((char*)&tmp,&(charset->widthtable),sizeof(tmp));
  
  return tmp;
}
  
//load height of font in bytes
inline uint8_t font_get_height_bytes(FONT_P charset) 
{
  uint8_t t = pgm_read_byte(&charset->height);
   
  return ((t-1)/8+1);
}

//is additional space needed to the right of the character?
inline uint8_t font_get_add_space(FONT_P charset, unsigned char character) 
{
  PGM_P type = font_widthtable(charset);
  
  if ( type != 0 ) //if there is a width table, then it's a proportional font
    return 1;
  else
    return 0;
}

//get character number in charset
inline int16_t font_get_char_number(FONT_P charset, unsigned char character) 
{
  uint8_t first = pgm_read_byte(&charset->firstchar);
  uint8_t last  = pgm_read_byte(&charset->lastchar);
  
  if (character < first || character > last) return -1;
    else return character - first;
}

//get width of character
inline uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
{
  PGM_P table = font_widthtable(charset);
  
  if (table)
    return pgm_read_byte(table+font_get_char_number(charset,character));
  else
    return pgm_read_byte(&charset->width);
}

//find position of character in flash
PGM_P font_get_char_position(FONT_P charset, unsigned char character) 
{
  uint16_t ret         = 0;
  int16_t  charnum_ret = font_get_char_number(charset, character);
  uint8_t  charnum     = charnum_ret;
  PGM_P    base        = font_widthtable(charset);

  if (charnum_ret < 0)          //char not found
    return 0;
  
  if(base == 0)            //fixed width
    return font_data(charset) + (uint16_t)charnum * (uint8_t)(font_get_height_bytes(charset) * font_get_char_width(charset,character));
  
  if (charnum)             //proportional width
    while(charnum--)
    ret += pgm_read_byte(base++);
    return (font_data(charset))+ret*font_get_height_bytes(charset);
}

//for double-height fonts: double all bits of a upper or lower nibble
inline unsigned char double_bits(uint8_t part, unsigned char c) 
{
  unsigned char t = 0;

  if (part) c >>= 4;
  if (c & 0x08) t |= 0xC0;
  if (c & 0x04) t |= 0x30;
  if (c & 0x02) t |= 0x0C;
  if (c & 0x01) t |= 0x03;
  
  return t;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ### lcd_draw_char(...) ###                                               
//
// Gibt ein Zeichen auf dem Display an der aktuellen Cursorposition aus
//
//   @parameter:  FONT_P charset         (gewünschter Zeichensatz; z.B. FONT_PROP_8)
//            uint8_t size           (gewünschte Schriftgröße; NORMAL_SIZE, DOUBLE_HEIGHT, DOUBLE_WIDTH oder DOUBLE_SIZE)
//            uint8_t u8_Style        (gewünschter Style; NORMAL_STYLE oder INVERTED_STYLE)
//            unsigned char character    (auszugebendes Zeichen)
// ...
//    @return   :  keine
//   
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) 
{
  int8_t  i;
  uint8_t row = 0; //current row of char
  uint8_t tmp;

  //load information about character
  uint8_t char_width    = font_get_char_width(charset,character); 
  uint8_t font_height   = font_get_height_bytes(charset);
  PGM_P   tableposition = font_get_char_position(charset,character);

  //final size of character
  uint8_t char_final_height = font_height; 
  
  uint8_t u8_ColCount = 0;

   //write chracter
  do 
  {
    for( i = (row) ; i < char_width * font_height ; i += font_height) 
    {
        
      if (character != 0x20)
      {
        tmp = pgm_read_byte(tableposition+i);
      }
      else
      {
        tmp = 0;
      }
      
      // Ausgabefenster setzen
      lcd_set_window( (u8_x_pos + u8_ColCount) , (u8_x_pos + u8_ColCount) ,u8_y_pos+(8*row),u8_y_pos+8+(8*row));

      lcd_send_byte(CMD, 0x2C);      

      for (uint8_t u8_col = 0 ; u8_col <= 7 ; u8_col++)
      {
        if (u8_Style == NORMAL_STYLE)
        {
          if (tmp & _BV(u8_col))
          {
            lcd_send_byte(PARA, u8_Brightness);
            lcd_send_byte(PARA, u8_Brightness);
          }
          else
          {
            lcd_send_byte(PARA, 0x00);
            lcd_send_byte(PARA, 0x00);
          }
        }
        else
        {
          // -> Invertierte Darstellung
          if (!(tmp & _BV(u8_col)))
          {
            lcd_send_byte(PARA, u8_Brightness);
            lcd_send_byte(PARA, u8_Brightness);
          }
          else
          {
            lcd_send_byte(PARA, 0x00);
            lcd_send_byte(PARA, 0x00);
          }
        }
      }

      u8_ColCount++;      

    }

    u8_ColCount = 0;
  } 
  while (++row < char_final_height);

} 



und hier in der neuen Variante wo aber wie gesagt etwas nciht stimmt 
beim font_data undfont_widthtable
//  FUNKTIONEN (Textausgabe)
// --------------------------

//load pointer to data table
const char* font_data(FONT_P charset) 
{
  const char* tmp;
  tmp = (charset.data);
  return tmp;
}


//load pointer to width table
const char* font_widthtable(FONT_P charset) 
{
  const char* tmp;
  tmp =(charset.widthtable);
  return tmp;
}
  
//load height of font in bytes
uint8_t font_get_height_bytes(FONT_P charset) 
{
  uint8_t t = (charset.height);
   
  return ((t-1)/8+1);
}

//is additional space needed to the right of the character?
uint8_t font_get_add_space(FONT_P charset, unsigned char character) 
{
  const char* type = font_widthtable(charset);
  
  if ( type != 0 ) //if there is a width table, then it's a proportional font
    return 1;
  else
    return 0;
}

//get character number in charset
inline int16_t font_get_char_number(FONT_P charset, unsigned char character) 
{
  uint8_t first = charset.firstchar;
  uint8_t last  = charset.lastchar;
  
  if (character < first || character > last) return -1;
    else return (character - first);
}

//get width of character
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
{
  const char* table = font_widthtable(charset);
  
  if (table)
    return (table+font_get_char_number(charset,character));
  else
    return (charset.width);
}

//find position of character in flash
char* font_get_char_position(FONT_P charset, unsigned char character) 
{
  uint16_t      ret         = 0;
  int16_t       charnum_ret = font_get_char_number(charset, character);
  uint8_t       charnum     = charnum_ret;
  const char*   base        = font_widthtable(charset);

  if (charnum_ret < 0)          //char not found
    return 0;
  
  if(base == 0)            //fixed width
    return font_data(charset) + (uint16_t)charnum * (uint8_t)(font_get_height_bytes(charset) * font_get_char_width(charset,character));
  
  if (charnum)             //proportional width
    while(charnum--)
    ret += (base++);
    return (font_data(charset))+ret*font_get_height_bytes(charset);
}

//for double-height fonts: double all bits of a upper or lower nibble
inline unsigned char double_bits(uint8_t part, unsigned char c) 
{
  unsigned char t = 0;

  if (part) c >>= 4;
  if (c & 0x08) t |= 0xC0;
  if (c & 0x04) t |= 0x30;
  if (c & 0x02) t |= 0x0C;
  if (c & 0x01) t |= 0x03;
  
  return t;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ### lcd_draw_char(...) ###                                               
//
// Gibt ein Zeichen auf dem Display an der aktuellen Cursorposition aus
//
//   @parameter:  FONT_P charset         (gewünschter Zeichensatz; z.B. FONT_PROP_8)
//            uint8_t size           (gewünschte Schriftgröße; NORMAL_SIZE, DOUBLE_HEIGHT, DOUBLE_WIDTH oder DOUBLE_SIZE)
//            uint8_t u8_Style        (gewünschter Style; NORMAL_STYLE oder INVERTED_STYLE)
//            unsigned char character    (auszugebendes Zeichen)
// ...
//    @return   :  keine
//   
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) 
{
  int8_t  i;
  uint8_t row = 0; //current row of char
  uint8_t tmp;

  //load information about character
  uint8_t char_width    = font_get_char_width(charset,character); 
  uint8_t font_height   = font_get_height_bytes(charset);
  char*   tableposition = font_get_char_position(charset,character);

  //final size of character
  uint8_t char_final_height = font_height; 
  
  uint8_t u8_ColCount = 0;

   //write chracter
  do 
  {
    for( i = (row) ; i < char_width * font_height ; i += font_height) 
    {
        
      if (character != 0x20)
      {
        tmp = (tableposition+i);
      }
      else
      {
        tmp = 0;
      }
      
      // Ausgabefenster setzen
      lcd_set_window( (u8_x_pos + u8_ColCount) , (u8_x_pos + u8_ColCount) ,u8_y_pos+(8*row),u8_y_pos+8+(8*row));

      lcd_send_byte(CMD, 0x2C);      

      for (uint8_t u8_col = 0 ; u8_col <= 7 ; u8_col++)
      {
        if (u8_Style == NORMAL_STYLE)
        {
          if (tmp & (1<<(u8_col)))
          {
            lcd_send_byte(PARA, u8_Brightness);
            lcd_send_byte(PARA, u8_Brightness);
          }
          else
          {
            lcd_send_byte(PARA, 0x00);
            lcd_send_byte(PARA, 0x00);
          }
        }
        else
        {
          // -> Invertierte Darstellung
          if (!(tmp & (1<<(u8_col))))
          {
            lcd_send_byte(PARA, u8_Brightness);
            lcd_send_byte(PARA, u8_Brightness);
          }
          else
          {
            lcd_send_byte(PARA, 0x00);
            lcd_send_byte(PARA, 0x00);
          }
        }
      }

      u8_ColCount++;      

    }

    u8_ColCount = 0;
  } 
  while (++row < char_final_height);

} 



Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hier nocheinmal die Strutkur
struct font_info {
    uint16_t size;                  //size of data array
    uint8_t  width;                 //(maximum) width of character
    uint8_t  height;                //height of character
    uint8_t  firstchar;             //the number of the first included character (often 0x20)
    uint8_t  lastchar;              //the last included character (often 0xFF)
    const char* widthtable;    //Pointer to the table holding character widths (NULL for monospaced fonts)
    const char* data;          //Pointer to data arrray
    };
typedef const struct font_info FONT_P;

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was um alles in der Welt hast du blos aus dem Originalcode gemacht.

<Kopfschüttel>

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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!

typedef const struct font_info * FONT_P;


//load pointer to data table
const char* font_data(FONT_P charset) 
{
  return charset->data;
}


//load pointer to width table
const char* font_widthtable(FONT_P charset) 
{
  return charset->widthtable;
}
  
//load height of font in bytes
uint8_t font_get_height_bytes(FONT_P charset) 
{
  uint8_t t = charset->height;
  return ((t-1)/8+1);
}

//is additional space needed to the right of the character?
uint8_t font_get_add_space(FONT_P charset, unsigned char character) 
{
  const char* type = font_widthtable(charset);
  
  if ( type != 0 ) //if there is a width table, then it's a proportional font
    return 1;
  else
    return 0;
}

//get character number in charset
inline int16_t font_get_char_number(FONT_P charset, unsigned char character) 
{
  uint8_t first = charset->firstchar;
  uint8_t last  = charset->lastchar;
  
  if (character < first || character > last) return -1;
    else return (character - first);
}

//get width of character
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
{
  const char* table = font_widthtable(charset);
  
  if (table)
    return table+font_get_char_number(charset,character);
  else
    return charset->width;
}

//find position of character in flash
char* font_get_char_position(FONT_P charset, unsigned char character) 
{
  uint16_t      ret         = 0;
  int16_t       charnum_ret = font_get_char_number(charset, character);
  uint8_t       charnum     = charnum_ret;
  const char*   base        = font_widthtable(charset);

  if (charnum_ret < 0)          //char not found
    return 0;
  
  if(base == 0)            //fixed width
    return font_data(charset) +
           (uint16_t)charnum * (uint8_t)(font_get_height_bytes(charset) * font_get_char_width(charset,character));
  
  if (charnum)             //proportional width
    while(charnum--)
      ret += *base++;

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

//for double-height fonts: double all bits of a upper or lower nibble
inline unsigned char double_bits(uint8_t part, unsigned char c) 
{
  unsigned char t = 0;

  if (part) c >>= 4;
  if (c & 0x08) t |= 0xC0;
  if (c & 0x04) t |= 0x30;
  if (c & 0x02) t |= 0x0C;
  if (c & 0x01) t |= 0x03;
  
  return t;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ### lcd_draw_char(...) ###                                               
//
// Gibt ein Zeichen auf dem Display an der aktuellen Cursorposition aus
//
//   @parameter:  FONT_P charset         (gewünschter Zeichensatz; z.B. FONT_PROP_8)
//            uint8_t size           (gewünschte Schriftgröße; NORMAL_SIZE, DOUBLE_HEIGHT, DOUBLE_WIDTH oder DOUBLE_SIZE)
//            uint8_t u8_Style        (gewünschter Style; NORMAL_STYLE oder INVERTED_STYLE)
//            unsigned char character    (auszugebendes Zeichen)
// ...
//    @return   :  keine
//   
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) 
{
  int8_t  i;
  uint8_t row = 0; //current row of char
  uint8_t tmp;

  //load information about character
  uint8_t char_width    = font_get_char_width(charset,character); 
  uint8_t font_height   = font_get_height_bytes(charset);
  char*   tableposition = font_get_char_position(charset,character);

  //final size of character
  uint8_t char_final_height = font_height; 
  
  uint8_t u8_ColCount = 0;

   //write chracter
  do 
  {
    for( i = (row) ; i < char_width * font_height ; i += font_height) 
    {
        
      if (character != 0x20)
      {
        tmp = tableposition[i];
      }
      else
      {
        tmp = 0;
      }
      
      // Ausgabefenster setzen
      lcd_set_window( (u8_x_pos + u8_ColCount) , (u8_x_pos + u8_ColCount) ,u8_y_pos+(8*row),u8_y_pos+8+(8*row));

      lcd_send_byte(CMD, 0x2C);      

      for (uint8_t u8_col = 0 ; u8_col <= 7 ; u8_col++)
      {
        if (u8_Style == NORMAL_STYLE)
        {
          if (tmp & (1<<(u8_col)))
          {
            lcd_send_byte(PARA, u8_Brightness);
            lcd_send_byte(PARA, u8_Brightness);
          }
          else
          {
            lcd_send_byte(PARA, 0x00);
            lcd_send_byte(PARA, 0x00);
          }
        }
        else
        {
          // -> Invertierte Darstellung
          if (!(tmp & (1<<(u8_col))))
          {
            lcd_send_byte(PARA, u8_Brightness);
            lcd_send_byte(PARA, u8_Brightness);
          }
          else
          {
            lcd_send_byte(PARA, 0x00);
            lcd_send_byte(PARA, 0x00);
          }
        }
      }

      u8_ColCount++;      

    }

    u8_ColCount = 0;
  } 
  while (++row < char_final_height);

} 


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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so ich habe das mal eingebunden und in folgenden zeilen
return (font_data(charset) + (uint16_t)charnum * (uint8_t)(font_get_height_bytes(charset) * font_get_char_width(charset,character)));

...

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

noch die Warnung

assignment makes integer from pointer without a cast

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Funktion font_data liefert als Rückgabewert einen Pointer.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die erste derartige Warnung kommt hier
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
{
  const char* table = font_widthtable(charset);
  
  if (table)
    return table+font_get_char_number(charset,character);
  else
    return charset->width;
}

und es muss lauten
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
{
  const char* table = font_widthtable(charset);
  
  if (table)
    return table[font_get_char_number(charset,character)];
  else
    return charset->width;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> bist du dir da sicher?

Ja
Bin ich

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tom (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich muss nen zeiger zurückgeben und habe zur verarbeitung einen 
zeiger plus einem Wert

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Tom (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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*'

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
struct font_info {
    uint16_t size;                  //size of data array
    uint8_t  width;                 //(maximum) width of character
    uint8_t  height;                //height of character
    uint8_t  firstchar;             //the number of the first included character (often 0x20)
    uint8_t  lastchar;              //the last included character (often 0xFF)
    const char* widthtable;    //Pointer to the table holding character widths (NULL for monospaced fonts)
    const char* data;          //Pointer to data arrray
    };

#ifdef FONTS_INCLUDE_font_vw_24px
  extern  const struct font_info font_vw_24px;
  #define FONT_VW_24 &font_vw_24px
#endif

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)};

//get width of character
uint8_t font_get_char_width(FONT_P charset, unsigned char character) 
{ LPC_GPIO2->FIODIR |= 0x01; // LED1
  const char* table = font_widthtable(charset);
  LPC_GPIO2->FIODIR |= 0x04; // LED3
  if (table)
  { 
    return (table[font_get_char_number(charset,character)]);
  }

//*table+font_get_char_number(charset,character);
  else
  {
    return (charset->width);
  }
}

//load pointer to width table
const char* font_widthtable(FONT_P charset) 
{  LPC_GPIO2->FIODIR |= 0x02; // LED2
  return charset->widthtable;
}

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

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hinter der struktur fehlt noch

typedef const struct font_info * FONT_P;


Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.