Forum: Compiler & IDEs Fonts in Array übergeben mit offset


von Andreas H. (andy78)


Lesenswert?

Hallo


Ich habe ein array mit Fontdaten.

Will zum bsp eine 0 ausgaben das offset liegt bei 360.


wenn ich die daten übergebe mache ich es so


&font_data,X,Y,width,height,layer

wenn ich nur die null in font_data habe geht es

aber wenn ich  &font_data+360 mache geht es nicht


wie kann ich den Zeiger auf die Position bringen???


Danke

gibt es auch irgendwie eine möglich keit den Text mit sprintf()
den kompletten text als einheit auszugeben.


Danke

von Huch (Gast)


Lesenswert?


von Stephan (Gast)


Lesenswert?

Ohne jetzt mehr von Deinem Code gesehen zu haben, brauchst Du wohl so 
was hier:

(&(font_data+360)),X,Y,width,height,layer

Man korrigiere mich bitte, wenn ich falsch liege (nachdem mehr Code 
gepostet wurde).
Stephan.

von Karl H. (kbuchegg)


Lesenswert?

Schwer zu sagen. Aber ich denke du liegst falsch.

Gemeint war wohl tatsächlich das hier
  &font_data[360]

was dem ürspünglichen

  &font_data+360

entspricht.

Aber ohne mehr Code, bzw. überhaupt mal Code, ist das praktisch nicht zu 
entscheiden.

von Andreas H. (andy78)


Lesenswert?

Hallo

Ja das mit den &font_data[offset] klappt.

ich habe ja da problm das ich immer nur 8 bit breite schreiben kann.#

Ich habe aber fonts mit 4 bit und mehr.

Ich habe mir gedacht das ich ein sprintf(buffer,"Wert1:%d\0",wert);

der buffer hat dann ja den inhalt Wert:12\0

diesen müsste ich dann auslesen

buffer[0]=W
buffer[1]=e
usw.

in meiner tabelle müsste ich dann schauen wo w liegt und wie breit w 
ist.

dann müsste ich ein mehrdimensionales arraymachen


[char(W),offset,width,height=imer gleich]

dann muß ich meine standart routine zum schreiben umändern


void GLCD_char(char * bmp, int x, int y, int width, int height,unsigned 
int layer)
{
unsigned int i, j;
for(i = 0; i < height ; i++)
  {
  GLCD_GraphicGoTo_pix(x, y+i,layer);
  GLCD_WriteCommand(SED1335_MWRITE);


  for(j = 0; j < width/8; j++)
    GLCD_WriteData(GLCD_ReadByteFromROMMemory(bmp+j+(i*(width/8))));
  }
}

von Andreas H. (andy78)


Lesenswert?

Hallo

habe mal probiert

ich schreibe zuerst den gesammten string mit den fontdaten in ein 
buffer.
es ist dann wie ein Bild.

dieses will ich dann ausgeben.
Leider sürzt mir den AVR ab (Speicherüberlauf).



void GLCD_chartext(char * text, unsigned int x, unsigned int y,unsigned 
int height,unsigned int layer)
{
uint32_t offset=0;
uint8_t index=0;
uint16_t width=0;
char *buffer;
unsigned int i=0, j,o;
for (int t=0;t<sizeof(text);t++)
{
  index =index_table[text[t]];
  offset=offset_table[index];
  width+=width_table[index];
  for (o=offset;o<offset_table[index+1];o++)
  {

  *buffer=&data_table[o];
  i++;


  }


}

if (width<8)width=8;
if (width>8 && width<16)width=16;
if (width>16 && width<24)width=24;

for(i = 0; i < height ; i++)
  {
  GLCD_GraphicGoTo_pix(x, y+i,layer);
  GLCD_WriteCommand(SED1335_MWRITE);



  for(j = 0; j < width/8; j++)
  {

    GLCD_WriteData(GLCD_ReadByteFromROMMemory(buffer+j+(i*(width/8))));
  }
}

}


Gruß

ANdy

von Andreas B. (Gast)


Lesenswert?

Andreas Herrmann schrieb:
> aber wenn ich  &font_data+360 mache geht es nicht

Entweder &font_data[360] oder font_data+360 gibt dir die Adresse des 
361. Elements von font_data.

Das ist aber nicht unbedingt das 361. Byte von font_data, wenn das deine 
Absicht ist. Additionen auf Zeiger funktionieren in Einheiten von der 
Größe des Datentypen, auf den gezeigt wird. Eine Addition gibt also nur 
dann ein Byte-Offset, wenn der Datentyp genau ein Byte groß ist.

von Andreas H. (andy78)


Lesenswert?

Hallo

habe es geschaft jetzt mache ich es set pixel weise ohne 8 bit 
beschränkung keine lästigen 8bit lücken mehr.

Aufruf
char buffer[20];
sprintf(buffer,"SAT in use:%d\0",3);

GLCD_chartext(&buffer,70,200,20,1);

//Funktion
void GLCD_chartext(char* text, unsigned int x, unsigned int y,unsigned 
int height,unsigned int layer)
{
uint32_t offset=0;
uint8_t index=0;
uint8_t width=0,width1;
unsigned char c;
unsigned int i=0, j,o=0,x1=0,p=0;
for (p=0;p<strlen(text);p++)
{

  index =index_table[text[p]];
  offset=offset_table[index];
  width=width_table[index];
  width1=width;




  if (width<8)width=8;
if (width>8 && width<16) width=16;
if (width>16 && width<24) width=24;


for(j=0;j<height;j++)
{
x1=x;
for(o=0;o<width/8;o++)
{
c=pgm_read_byte(&data_table[offset+o+(j*(width/8))]);
for(i=0;i<8;i++)
{

  if (c&(128>>i))
  {
GLCD_SetPixel(x1+i,y+j,1,1);
}
else
{
GLCD_SetPixel(x1+i,y+j,0,1);
}


}

x1+=8;
}
}
  x+=width1;
}
}


Der code ist sicherlich verbesserungswürdig aber funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

Da es sich hier um eine Basisroutine handelt, die flott laufen soll:

Hände weg von strlen!
Das brauchst du auch nicht.

Wenn du jedes einzelne Zeichen eines Strings bearbeiten willst, dann 
machst du das so
1
void GLCD_chartext(char* text, unsigned int x, unsigned int y,
2
                   unsigned int height,unsigned int layer)
3
{
4
  ...
5
6
  while( *text != '\0' )
7
  {
8
    index = index_table[ *text++ ];
9
10
    offset = offset_table[index];
11
    width  = width_table[index];
12
    width1 = width;
13
14
    if( width < 8 )
15
      width = 8;
16
17
    if( width < 16 )
18
      width = 16;
19
20
    for( j = 0; j < height; j++ )
21
    {
22
      x1 = x;
23
24
      byteOffset = j*(width/8);
25
26
      for( o = 0; o < width/8; o++ )
27
      {
28
        c = pgm_read_byte( &data_table[ offset + o + byteOffset ] );
29
30
        for( i = 0; i < 8; i++ )
31
        {
32
          if( c & (128>>i) )
33
          {
34
            GLCD_SetPixel( x1+i, y+j, 1, 1 );
35
          }
36
          else
37
          {
38
            GLCD_SetPixel( x1+i, y+j, 0, 1 );
39
          }
40
        }
41
42
        x1 += 8;
43
      }
44
    }
45
46
    x += width1;
47
  }
48
}

und achte ein wenig mehr auf eine anständige Code-Formattierung. Sonst 
wirst du irgendwann ganz grauslich auf die Nase fallen.

von Andreas H. (andy78)


Lesenswert?

Hallo Karl heinz

Vielen Dank

habe den code leich ausprobiert und siehe da es ist bedeutend schneller 
beim aufbau.

Mein Problem ist, ich beschäftige mich zu wenig damit und vorallen mit 
C.


Vielen Dank

Gruß

Andy

von Karl H. (kbuchegg)


Lesenswert?

Da ist noch ein Zeitfresser

     if( c & (128>>i) )

von Rolf M. (rmagnus)


Lesenswert?

Karl heinz Buchegger schrieb:
> Da ist noch ein Zeitfresser
>
>      if( c & (128>>i) )

Besser wäre z.B:
1
uint_fast8_t bitvalue = 128;
2
for(i=0;i<8;i++)
3
{
4
5
  if (c & bitvalue)
6
  {
7
      // ...
8
  }
9
10
  // ...
11
12
  bitvalue >>= 1;
13
}

von Andreas H. (andy78)


Lesenswert?

Hallo

Vielen Dank für deine Mühen.

Der Code funktioniert nicht denke es werden alles nullen weil ich nichts 
angezeigt bekomme.


Habe mal eine andere Frage

gibt es eine möglichkeit (Tankanzeige 0-90 grad) einen Kreisbogen der ca 
5 pixel breit zeichen z.b 90Grad = voll 0 grad leer 45 Grad halbvoll.

Wäre super

Vielen Dank

Gruß

Andy

von Karl H. (kbuchegg)


Lesenswert?

Andreas Herrmann schrieb:
> Hallo
>
> Vielen Dank für deine Mühen.
>
> Der Code funktioniert nicht denke es werden alles nullen weil ich nichts
> angezeigt bekomme.

Welcher Code?

Kann natürlich auch sein, dass du jetzt einen anderen Fehler eingebaut 
hast. :-)


> gibt es eine möglichkeit (Tankanzeige 0-90 grad) einen Kreisbogen der ca
> 5 pixel breit zeichen z.b 90Grad = voll 0 grad leer 45 Grad halbvoll.
>
> Wäre super

zb. Bresenham in der Variante für Kreise bzw Kreisbögen (danach 
googeln).

Da das aber ein Anzeigehintergrund ist, kann man das auch einfach 
mittels der Kreisgleichung machen.
    x^2 + y^2 = r^2
umstellen nach y und x laufen lassen. Die Wurzel ist an dieser Stelle 
auch nicht so sehr das große Problem und Verfahren für Integer Wurzeln 
sind ja auch schon erfunden. Allerdings kann es auch hier passieren, 
dass vor allem am Ende, wenn x sich immer mehr r annähert, Löcher 
entstehen.

Nächste VAriante:
Einen Winkel zb von 0 bis 90 Grad laufen lassen, dann

    x = r * cos( alpha )
    y = r * sin( alpha )

und zwischen sukzessiven Punkten jeweils Linien zeichen. Je feiner man 
den Winkel auflöst, desto weniger sieht man, dass man eigentlich ein 
Vieleck gemalt hat und keinen Kreis. Bei ganz kleinen Winkelinkrementen 
braucht man dann überhaupt nur noch Punkte setzen und kann sich die 
Linien sparen.


Allen gemeinsam ist aber das Problem:
Alle Linienzeichenverfahren bauen immer darauf auf eine 1 Pixel breite 
Linie/Bogen/was auch immer) zu malen.

Natürlich kann man zb 5 Bögen um 1 Pixel versetzt malen. Dann läuft man 
aber Gefahr, dass enizelne Pixel nicht überdeckt werden.

Eine andere Variante besteht darin, gedanklich an der fraglichen 
Position keine Pixel zu setzen, sondern mit einem Stift einen 'Punkt' zu 
malen. Wobei natürlich dann nebeneinanderliegende Punkte viele Pixel 
doppelt und dreifach übermalen. Aber zumindest das Endergebnis stimmt.


PS: Ich würde an deiner Stelle mit

    x = r * cos( alpha )
    y = r * sin( alpha )

arbeiten. Um sin/cos kommst du spätestens beim Zeiger sowieso nicht mehr 
rum und die Funktionen lassen sich wiederrum gut und schnell mittels 
einer Tabelle abbilden, wenn man auf Floating Point verzichten will.

von Andreas H. (andy78)


Lesenswert?

Hallo

Habe es doch mit Zeigern gelöst.

geht auch so.

danke

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.