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.
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?
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?
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.
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 =)
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.
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...
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.
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]
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.
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
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!
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
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.
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.
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
inlinePGM_Pfont_data(FONT_Pcharset)
3
{
4
PGM_Ptmp;
5
tmp=(PGM_P)pgm_read_word(&(charset->data));
6
returntmp;
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
constchar*font_data(FONT_Pcharset)
2
{
3
constchar*tmp;
4
tmp=(charset.data);
5
returntmp;
6
}
diese Funktion wird nun in einem Teil für die genaue Position des
Zeichens in der Datentabelle benötigt
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 =)
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.
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.
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
typedefconststructfont_info*FONT_P;
2
3
4
//load pointer to data table
5
constchar*font_data(FONT_Pcharset)
6
{
7
returncharset->data;
8
}
9
10
11
//load pointer to width table
12
constchar*font_widthtable(FONT_Pcharset)
13
{
14
returncharset->widthtable;
15
}
16
17
//load height of font in bytes
18
uint8_tfont_get_height_bytes(FONT_Pcharset)
19
{
20
uint8_tt=charset->height;
21
return((t-1)/8+1);
22
}
23
24
//is additional space needed to the right of the character?
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.
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.
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.
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
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.
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.
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?
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?
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*'
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
structfont_info{
2
uint16_tsize;//size of data array
3
uint8_twidth;//(maximum) width of character
4
uint8_theight;//height of character
5
uint8_tfirstchar;//the number of the first included character (often 0x20)
6
uint8_tlastchar;//the last included character (often 0xFF)
7
constchar*widthtable;//Pointer to the table holding character widths (NULL for monospaced fonts)
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?
ü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