www.mikrocontroller.net

Forum: Compiler & IDEs GLCD variabel invertieren ?


Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein 128x64 GLCD Display und habe dafür ein Menü geschrieben, in 
welchem über zwei Taster die einzelnen Menüpunkte ausgewählt werden 
sollen. Hierbei soll der ausgewählte Menüpunkt invertiert angezeigt 
werden.

Ich habe bereits eine Fkt. die den kompletten Inhalt im Dispay 
invertiert aber wie mache ich es, das nur ein bestimmter Bereich 
invertiert wird ?
Problem ist hierbei das, dass Display mit zwei Chips betreiben wird 
(linke und rechte Hälfte) und ich nicht weiß wie ich das miteinander 
Verbinden soll ?!

Wer hat eine Idee oder eine schon fertige Funktion ?


Hier mal die Fkt. um die komplette anzeige auf dem Disp. zu invertieren.
void lcd_invert()
{

  uint8_t x,y,data;

  for (y=0;y<8;y++)
  {
    lcd_write_cmd(LCD_SET_PAGE|y,CHIP1);
    lcd_write_cmd(LCD_SET_PAGE|y,CHIP2);  //set page on both controllers

    for (x=0;x<=63;x++)
    {
      lcd_write_cmd(LCD_SET_ADD|x,CHIP1);  
      data=lcd_read_data(CHIP1);
      lcd_write_cmd(LCD_SET_ADD|x,CHIP1);  //read two times (dont know why, but else i get buggy outpur)
      data=lcd_read_data(CHIP1);

      lcd_write_cmd(LCD_SET_ADD|x,CHIP1);  
      lcd_write_data(~data,CHIP1);    //set inverter data
      
      lcd_write_cmd(LCD_SET_ADD|x,CHIP2);  // do the same on the second controller
      data=lcd_read_data(CHIP2);
      lcd_write_cmd(LCD_SET_ADD|x,CHIP2);  
      data=lcd_read_data(CHIP2);

      lcd_write_cmd(LCD_SET_ADD|x,CHIP2);  
      lcd_write_data(~data,CHIP2);    
    }
  }

  lcd_write_cmd(LCD_SET_ADD|0,CHIP1);
  lcd_write_cmd(LCD_SET_ADD|0,CHIP2);    //set hom home pos
  lcd_write_cmd(LCD_SET_PAGE|0,CHIP1);
  lcd_write_cmd(LCD_SET_PAGE|0,CHIP2);

  invert++;
  invert %=2;
}

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

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:

> Ich habe bereits eine Fkt. die den kompletten Inhalt im Dispay
> invertiert aber wie mache ich es, das nur ein bestimmter Bereich
> invertiert wird ?
> Problem ist hierbei das, dass Display mit zwei Chips betreiben wird
> (linke und rechte Hälfte) und ich nicht weiß wie ich das miteinander
> Verbinden soll ?!
>
> Wer hat eine Idee oder eine schon fertige Funktion ?

Üblich sind 2 Vorgehensweisen:
Wenn alle Stricke reißen, macht man sich eine Textausgabefunktion, die 
den Text invertiert ausgibt.

Ansonsten dann eben eine Invertierfunktion, die ein Rechteck invertiert. 
Dann braucht man auch die Komplett-Invertierfunktion nicht mehr, die ist 
dann einfach nur ein Sonderfall davon.

> Problem ist hierbei das, dass Display mit zwei Chips betreiben
> wird (linke und rechte Hälfte) und ich nicht weiß wie ich das
> miteinander Verbinden soll ?!

Aufmalen mit Papier und Bleistift.
Welche Fälle gibt es? Wie müssen sie daher behandelt werden?
Eine Funktion schreiben, die ein Rechteck, welches komplett am linken 
Controller liegt, invertiert. Eine Funktion, die dasselbe beim rechten 
Controller macht. Darüber dann noch eine Funktion legen, die ein 
beliebiges Rechteck in den Teil für den linken Controller und für den 
rechten Controller aufteilt und die beiden Hilfsfunktionen nach Bedarf 
mit den aufgeteilten Rechtecken aufruft.
Damit bist du dann schon mal die Aufteilung in links/rechts los.
Jetzt bleibt nur noch das 'Problem', dass du nicht mehr einfach nur ein 
Byte vom LCD lesen, invertieren und zurückschreiben kannst. Denn 
natürlich sagt kein Mensch, dass der zu invertierende Bereich genau auf 
einer Zeilengrenze anfängt.
Aber du kannst das Rechteck unterteilen:

       erste Page                (hier werden nur die relevant
                                  übereinanderliegenden Pixel invertiert

       Pages dazwischen          die werden als Ganzes einfach
                                 invertiert, da alle 8 übereinander
                                 liegenden Pixel betroffen sind

       letzte Page               bekommt wie die erste Page eine
                                 Sonderbehandlung, weil ja nicht einfach
                                 nur das Byte invertiert werden kann,
                                 sondern nur einzelne Bits davon


Einen Sonderfall gibt es noch: wenn Ober- und Unterkante des Rechtecks 
beide in der ersten Page enthalten sind.


Die Devise heißt oft nicht: die eierlegende Wollmilchsau-Funktion zu 
schreiben, sondern: ein komplexes Problem in einfachere Teilprobleme 
aufzuteilen und die Teilprobleme mittels eigenen Funktionen lösen 
lassen.

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich probiert mich mal an so einer Fkt. aus... bei mir müssen eigentlich 
immer nur Rechtecke invertiert werden, da mein Menü tabellarisch 
aufgebaut ist.
Was ich noch nicht verstehe (siehe die Fkt. obene), warum werden in der 
y-Richtung immer gleich 8 Pixel auf einmal angesprochen aber in die 
x-Richtung dafür einzeln ?

Danke Andreas

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

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:

> Was ich noch nicht verstehe (siehe die Fkt. obene), warum werden in der
> y-Richtung immer gleich 8 Pixel auf einmal angesprochen aber in die
> x-Richtung dafür einzeln ?

Weil auf dem LCD offenbar die 8 Bits eines Bytes als 
übereinanderliegende Pixel dargestellt werden.

Du hast doch das LCD vor dir. Hast du mit dem Ding noch nie gespielt und 
dir in Natura angesehen, wie das funktioniert?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:
> warum werden in der
> y-Richtung immer gleich 8 Pixel auf einmal angesprochen aber in die
> x-Richtung dafür einzeln ?

Weil man beim ks0108, um den es hier anscheinend geht, nunmal nur so auf 
die Pixel zugreifen kann.

Anscheinend hast du ja schon eine lib dafür gefunden. Damit hast du doch 
schon ein Beispiel, wie das mit den zwei Chips so geht.

Mit etwas Mühe, google, und ein paar Minuten Zeit findest du sicherlich
a) ein Datenblatt zum ks0108
b) weitere fertige libs für gcc und AVR
c) alles andere, was man so wissen muß

libs gibt es hier in der Codesammlung. Sogar mit Invertierfunktion.

Oliver

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl Heinz:
Es ist das erste mal das ich mit einem LCD Display etwas zu tun habe. 
Wie Oliver schon festgestellt hat, handelt es sich hier um ein KS0108 
Display.

Werde mich heute an die "variable" invertier Funktion  machen und mein 
Erg. dann mal posten.

Danke und Gruß
Andreas

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe das Problem jetzt doch schneller gelöst als gedacht.

Ich habe für mein Menü eine Tabelle gezeichnet und in jede Zelle einen 
Menüpunkt dargestellt.
Da meine LCD Lib eine Funktion beinhaltet, die gezeichnete Rechtecke 
"ausfüllt", habe ich einfach diese Funktion hergenommen und fülle die 
entsprechende Zelle aus. Die Funktion mit der ich komplette Strings auf 
das Display schreibe habe ich um die Eigenschaft erweitert eine "Farbe" 
zu übergeben.
Somit überschreibe ich einfach den Inhalt von schwarz-weiß auf 
weiß-Schwarz.
// ---------------------------------
// put char to screen
// ---------------------------------
void lcd_putc(uint8_t* font,uint8_t chr, uint8_t color)
{
  uint8_t x,page,bit,data,cnt=0;
  
  if (font_char_present(font,chr)==1)  // print only if letter is present in font
  {
    if ( ( (cursor_x + font_char_width(font,chr)) <128)  && ((cursor_y+font_char_height(font))<=64))  // only print leeter if it fits in screen
    {
      uint16_t offset= font_start_offset(font,chr);  // get the position of the first byte in font-array
      
      for(page=0;page<=(font_char_height(font)-1)/8;page++)  // write all pages(rows)
      {
        lcd_write_cmd(LCD_SET_PAGE|((cursor_y/8)+page),CHIP1|CHIP2);  // calc the current page

        if (cursor_x<64)  // set cursor to its poition (0 on the inactive controller so it can start directly on chip change)
        {
          lcd_write_cmd(LCD_SET_ADD|cursor_x,CHIP1);
          lcd_write_cmd(LCD_SET_ADD|0,CHIP2);
        }
        else
        {
          lcd_write_cmd(LCD_SET_ADD|(cursor_x-64),CHIP2);        
        }

        for (x=cursor_x;x<cursor_x + font_char_width(font,chr);x++)  //fill "pages"
        {
          data= pgm_read_byte(font+offset+cnt++);

          if ( page==font_char_height(font)/8)    
            data>>=8-(font_char_height(font)%8);  // if char height is bigger than 8 we have to remove some leading zeros
          
          #ifdef FASTTEXT                // this is much much faster than using set_pixel (see discription in header file)
          if (cursor_y%8==0 )
          {
            if (x<64)                
              lcd_write_data(data,CHIP1);            
            else                  
              lcd_write_data(data,CHIP2);          
          }
          else
          #endif
          {
            for (bit=0;bit<8;bit++)
            {
              if ((data&(1<<bit))!=0)
               lcd_set_pixel(x,cursor_y+page*8+bit,color);
            }
          }
        }      
        
        #ifdef FASTTEXT
        if(cursor_y%8==0)
        {
          if (x<64)                
            lcd_write_data(0,CHIP1);            
          else                  
            lcd_write_data(0,CHIP2);        
        }
        #endif
      }      
      cursor_x += font_char_width(font,chr)+1;


    }
  }
}

// ------------------------------------
// fills an rectangle with given color
// ------------------------------------

void lcd_fill_rect(uint8_t x,uint8_t y,uint8_t width,uint8_t height,uint8_t color)
{
  uint8_t cnt_x,cnt_y;
    for (cnt_y=y;cnt_y<y+height;cnt_y++)        // fill screen using set_pixel (slow) but needs less memory
      for (cnt_x=x;cnt_x<x+width;cnt_x++)
        lcd_set_pixel(cnt_x,cnt_y,color);

}

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.