Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ROZNE][C] - Zamiana tablic znaków

16 Lis 2009 18:41 2554 7
  • Poziom 23  
    Mam taki problem.
    Posiadam 2 tablice znaków (charset[] i charset2[] z różnymi czcionkami oraz funkcję wyświetlającą te znaki:

    Code:
    uint8_t LCD_Char(int8_t mychr, uint8_t xPos, uint8_t yPos,) {
    

       mychr -= pgm_read_byte(&(charset[1])); //odczyt offsetu, czyli 32, odjecie od znaku 32
       uint8_t height = pgm_read_byte(&(charset[0])) & 3; // odczyt wysokosci znaku, czyli 0x00
       height++; // wysokosc +1
       uint8_t h, x, y, out;
        uint16_t cnt = 0;
       uint8_t width; // szerokosc

       for(x = 0; x < (mychr*height); x++) {
          cnt += getNibble(x+6); //ktory bajt z tablicy znakow (od 32)
       }
       width = getNibble(x+6); // szerokosc konkretnego znaku

       cnt += (pgm_read_byte(&(charset[2]))+1)/2; // odaje do cnt liczbe bajtow przed pierwszym znakiem
       cnt +=3; //+ te 3 z poczatku
       for(h = 0; h < height; h++) {
          for(x = 0; x < width; x++) {
             out = pgm_read_byte(&(charset[cnt+x]));
             for(y = 0; y < 8; y++) {
                if(out & 1) {
                   LCD_Pixel(xPos + x, yPos + y);
                }
                out >>= 1;
             }
          }
          yPos += 8;
          cnt+=width;
       }
       return width;
    }


    Jak widać wświetla poprawnie dla pierwszej tablicy. Ale np chcę wyświetlić znaki z drugiej tablicy i tu jest problem. Myślałem nad przekazaniem przez zmienną informacji zmianie tablicy i zmienić ją w ciele tej funkcji, ale nie wiem jak to zrobić (z charset[] na charset2[]). Próbowałem przez wskaźniki na tablice ale nie wyszło mi. Jedynie do głowy przychodzi mi wszędzie gdzie jest odczyt z tablicy za pomocą instrukcji if zmieniać ją, ale takie if musiało by być 4, do tego 2 w instrukcji getNibble(). Powielenie tej funkcji, tak, żeby wyświetlała drugą tablice też nie wchodzi w grę (brak miejsca w uC).
    Myślałem też nad tablicą globalną, do której kopiowało by się dane z charset[] lub charset2[], ale to bez sensu, za dużo miejsca zajmuje. Utrudnieniem jest też to, że jedna tablica ma ok 1000bajtow, druga ze 100).
    Jakieś pomysły?
  • Poziom 33  
    Ale zamieszałeś :wink:. To w końcu w tych tablicach masz dwie rożne czcionki czy w jednej trzymasz dane czcionki a w drugiej ich wysokość?
  • Poziom 23  
    Heh, w tym rzecz, że te tablice są nietypowe, są w nich i wysokości i znaki.

    Chodzi o to, że raz chcę skorzystać z jednej tablicy znaków (mniejsza czcionka), drugi raz z drugiej tablicy (większa czcionką) i wyświetlić znaki za pomocą jednej funkcji. Wybór byłby dokonywany przez wywołanie funkcji (na jej końcu albo 0 albo 1).
    I wszystko ok, ale nie wiem jak zmienić tablice w samej funkcji (przełączyć ją z jednej na drugą, jeśli wywołamy funkcję z parametrem 1 na końcu).

    Np dopisuje do uint8_t LCD_Char(int8_t mychr, uint8_t xPos, uint8_t yPos, uint8_t czcionka)

    I wywołuje:
    LCD_Char("napis", 30, 30,0] - wyświetla napis ze znakow z tablicy charset[]
    LCD_Char("napis", 30, 30,1] - wyświetla napis ze znakow z tablicy charset2[]

    Przykładową tablicę znaków jaką potrafi wyświetlić ta funkcja zamieściłem tu: https://www.elektroda.pl/rtvforum/viewtopic.php?t=1479654&highlight=
  • Pomocny post
    Moderator Mikrokontrolery Projektowanie
    Jesli te tablice maja taka sama strukture to prosciej do funkcji przekazac wskaznik do wlasciwej tablicy:
    uint8_t LCD_Char(int8_t mychr, uint8_t xPos, uint8_t yPos, char *tablica)

    i potem wywolywac:
    uint8_t LCD_Char(..., &tablica1[0])
    lub
    uint8_t LCD_Char(..., &tablica2[0])
  • Pomocny post
    Poziom 33  
    Myrek1 napisał:
    ..... ale nie wiem jak zmienić tablice w samej funkcji (przełączyć ją z jednej na drugą, jeśli wywołamy funkcję z parametrem 1 na końcu).


    Wystarczy zastosować wskaźnik do tabeli i w zależności od parametru przypisać mu adres [pierwszej lub drugiej tablicy.
    Co do samego "zdekodowania" danych z tablicy to niestety trzeba się dowiedzieć "co autor miał na myśli" a jeżeli to był jeszcze rodowity Niemiec....to oni mają czasami nieźle "przekombinowane" rozwiązania.
    Moja tablica ze wszystkimi pisanymi z klawiatury znakami + polskie znaki zgodnie z kodowaniem CP1251 zajmuje ~1850B. Czcionka to Times New Roman 10px...czyli jakieś średnio 9x6.
  • Poziom 23  
    Faktycznie :) Próbowałem ze wskaźnikami, ale nie przez przekazywanie. Faktycznie, tak najlepiej i najszybciej.

    Ten zapis tablicy i wyświetlania znaków rozgryzłem już. Faktycznie ten Niemiec pomieszał strasznie, ale za to jest bardzo oszczędna ta tablica. Ona ma jeszcze symbole, łącznie ma 224znaki i zajmuje 1074 bajty, czcionka o wysokości 8pix, szerokość zmienna, zależna od znaku (inna dla np "O", a inna dla "!" ).

    Bardzo fajna ta czcionka, mało zajmuje i większy string się mieści. Problem tylko z zrobieniem swojej zgodnie z tą zasadą, trzeba ręcznie :(

    A Skalowania nie ma, trzeba robić swoją czcionkę większą. Autor nie przetestował tej funkcji i trzeba było trochę zmienić, żeby można było wyświetlać fonty x2, x4

    @markosik20
    Można jeszcze funkcję do wyświetlania tego?
  • Poziom 33  
    Myrek1 napisał:
    Można jeszcze funkcję do wyświetlania tego?


    Proszę bardzo.
    Do generowania plików .c mam specjalny programik (niestety jest płatny komercyjny) który pozwala wygenerować plik dla każdej czcionki w systemie.
    Dodatkowo dla dużych czcionek wystarczy wpisać tylko interesujące nas znaki np: same cyfry (żeby tablica nie była duża). Funkcja sama weryfikuje czy jest definicja znaku i gdzie ona się znajduje.
    Kreśli znaki dokładnie tak jak w PC (litery j,y,g,q itd. odpowiednio niżej, a ' lub np: ° odpowiednio wyżej).

    Code:


    #define code const
    #define FONTGEN_USE_PRECALCULATED_OFFSETS
    #define FONTGEN_USE_MAPPING_TABLE
    #define NULL 0

    typedef  struct _GLYPH_DET
          {
          const unsigned char    top;     // the number of lines removed from the top of the char
             const unsigned char     bottom;    // the number of lines removed from the bottom of the char
          } GLYPH_DET;

    typedef struct _FONT_DEF
          {
             const unsigned char   glyph_width;        /* glyph width in pixels 0 for variable width fonts     */
             const unsigned char   glyph_height;       /* glyph height for storage           */
             const unsigned char   *glyph_table;           /* font table start address in memory */
             const unsigned char   *mapping_table;         /* used to find the index of a glyph  */
             const unsigned char   *width_table;           /* width table start adress           */
             const unsigned short  *offset_table;          /* keeps the offsets of the first byte of each glyph */
             GLYPH_DET             *detail_table;
          }FONT_DEF;

    typedef struct _ASCII
          {
          unsigned int x;
          unsigned int y;
          unsigned char tlo;
           const FONT_DEF  *font;
          unsigned int color_bcg;
          unsigned int color_char;
          unsigned char znak;
          unsigned char numer_czcionki;
          }ASCII;

    ASCII Param_char;

    void SetParameterFont (unsigned char x, unsigned char y, unsigned int color, unsigned int background, unsigned char number_font)
    {
       Param_char.x=x;
       Param_char.y=y;

        if(background)Param_char.tlo = 1;
        else Param_char.tlo = 0;

         Param_char.color_bcg = background;
         Param_char.numer_czcionki = number_font;
         Param_char.color_char = color;
         Laduj_Numer_czcionki(Param_char.numer_czcionki);
     }

    unsigned short CharOnLCD  (void)
    {


      unsigned char height,width,h,w,k,sz;
      unsigned short dy,dx=0;

      signed char start_line;
      unsigned short offset;
      unsigned char  znak=0,mask;
      unsigned char const *ptrTab;



      //if not define char
      if(Param_char.znak != 0x20 && *(Param_char.font->mapping_table + Param_char.znak) == 0 )return Param_char.x;

      offset = *(Param_char.font -> offset_table  + *(Param_char.font->mapping_table + Param_char.znak));

      //wskaznik do poczatku danych tabeli znakow
      ptrTab = Param_char.font -> glyph_table + offset;

      offset = *(Param_char.font->mapping_table + Param_char.znak);

      //okreslenie szerokosci znkaow przy wykorzytsaniu offsetu w tabeli
      if(Param_char.font -> glyph_width == 0)
      {
         width = *(Param_char.font -> width_table + offset);
      }
      else
      {
         width = Param_char.font -> glyph_width;
      }


      if(Param_char.font -> detail_table)
      {
         height =    (Param_char.font->detail_table + offset)->bottom + 1 -
                   (Param_char.font->detail_table + offset)->top;
         start_line = Param_char.font->glyph_height - (Param_char.font->detail_table + offset)->top - height ;

      }
      else
      {
         height = Param_char.font->glyph_height;
         start_line = 0;
      }

      dy = Param_char.y + height + start_line;
      dx = Param_char.x;
      for(sz=0;sz<width;sz++)
      {
         if(Param_char.tlo)   pixel(dx+sz,dy+1,Param_char.color_bcg);
      }

      for (h=0; h < height; h++)
      {
          mask = 0;
           dx = Param_char.x;

           w = width;

          for(sz=0; sz < width; sz+=8)
          {
             znak = *ptrTab;
             ptrTab++;

             if(w>8)k=8;
             else k = w;

              for (; k>0; k--)  //wyswietl pixele znaku na lcd
               {
                    if (znak & 0x80)
                  {
                     pixel(dx,dy,Param_char.color_char);
                  }
                  else
                  {
                     if(Param_char.tlo)
                   {
                      pixel(dx,dy,Param_char.color_bcg);
                   }
                }

                znak <<=1;
                dx++;
               }
              w-=8;
          }

          if(Param_char.tlo)   pixel(dx,dy,Param_char.color_bcg);
          dy--;

      }


      for(sz=0;sz<width;sz++)
      {
           if(Param_char.tlo)   pixel(Param_char.x+sz,dy,Param_char.color_bcg);
      }

      return dx;

    }
  • Moderator Mikrokontrolery Projektowanie
    W sumie to ciekawy pomysl, zeby zamiast zapisywac kolejne linie czcionki poziomo (co nawet w przypadku "i" daje 8 bajtow) zapisywac je pionowo, co dla wspomnianego "i" da jeden bajt. Wyswietlanie takiej czcionki wcale nie bedzie bardziej skomplikowane. Kiedys popelnilem program konwertujacy dowolna czcionke z pliku fon lub fnt na bitmapy zdatne do nakarmienia nimi AVRa i wygenerowania stosownego pliku naglowkowego. Chyba go przerobie tak, zeby generowac tak "dziwnie" skompresowane pliki fontow.
    Plikow ttf nie ma co czytac, bo dla tak niskich rozdzielczosci lepsze efekty daje korzystanie z prerenderowanych fontow.