Forum: Compiler & IDEs GLCD variabel invertieren ?


von Andreas P. (Gast)


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.
1
void lcd_invert()
2
{
3
4
  uint8_t x,y,data;
5
6
  for (y=0;y<8;y++)
7
  {
8
    lcd_write_cmd(LCD_SET_PAGE|y,CHIP1);
9
    lcd_write_cmd(LCD_SET_PAGE|y,CHIP2);  //set page on both controllers
10
11
    for (x=0;x<=63;x++)
12
    {
13
      lcd_write_cmd(LCD_SET_ADD|x,CHIP1);  
14
      data=lcd_read_data(CHIP1);
15
      lcd_write_cmd(LCD_SET_ADD|x,CHIP1);  //read two times (dont know why, but else i get buggy outpur)
16
      data=lcd_read_data(CHIP1);
17
18
      lcd_write_cmd(LCD_SET_ADD|x,CHIP1);  
19
      lcd_write_data(~data,CHIP1);    //set inverter data
20
      
21
      lcd_write_cmd(LCD_SET_ADD|x,CHIP2);  // do the same on the second controller
22
      data=lcd_read_data(CHIP2);
23
      lcd_write_cmd(LCD_SET_ADD|x,CHIP2);  
24
      data=lcd_read_data(CHIP2);
25
26
      lcd_write_cmd(LCD_SET_ADD|x,CHIP2);  
27
      lcd_write_data(~data,CHIP2);    
28
    }
29
  }
30
31
  lcd_write_cmd(LCD_SET_ADD|0,CHIP1);
32
  lcd_write_cmd(LCD_SET_ADD|0,CHIP2);    //set hom home pos
33
  lcd_write_cmd(LCD_SET_PAGE|0,CHIP1);
34
  lcd_write_cmd(LCD_SET_PAGE|0,CHIP2);
35
36
  invert++;
37
  invert %=2;
38
}

von Karl H. (kbuchegg)


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.

von Andreas P. (Gast)


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

von Karl H. (kbuchegg)


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?

von Oliver (Gast)


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

von Andreas P. (Gast)


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

von Andreas P. (Gast)


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.
1
// ---------------------------------
2
// put char to screen
3
// ---------------------------------
4
void lcd_putc(uint8_t* font,uint8_t chr, uint8_t color)
5
{
6
  uint8_t x,page,bit,data,cnt=0;
7
  
8
  if (font_char_present(font,chr)==1)  // print only if letter is present in font
9
  {
10
    if ( ( (cursor_x + font_char_width(font,chr)) <128)  && ((cursor_y+font_char_height(font))<=64))  // only print leeter if it fits in screen
11
    {
12
      uint16_t offset= font_start_offset(font,chr);  // get the position of the first byte in font-array
13
      
14
      for(page=0;page<=(font_char_height(font)-1)/8;page++)  // write all pages(rows)
15
      {
16
        lcd_write_cmd(LCD_SET_PAGE|((cursor_y/8)+page),CHIP1|CHIP2);  // calc the current page
17
18
        if (cursor_x<64)  // set cursor to its poition (0 on the inactive controller so it can start directly on chip change)
19
        {
20
          lcd_write_cmd(LCD_SET_ADD|cursor_x,CHIP1);
21
          lcd_write_cmd(LCD_SET_ADD|0,CHIP2);
22
        }
23
        else
24
        {
25
          lcd_write_cmd(LCD_SET_ADD|(cursor_x-64),CHIP2);        
26
        }
27
28
        for (x=cursor_x;x<cursor_x + font_char_width(font,chr);x++)  //fill "pages"
29
        {
30
          data= pgm_read_byte(font+offset+cnt++);
31
32
          if ( page==font_char_height(font)/8)    
33
            data>>=8-(font_char_height(font)%8);  // if char height is bigger than 8 we have to remove some leading zeros
34
          
35
          #ifdef FASTTEXT                // this is much much faster than using set_pixel (see discription in header file)
36
          if (cursor_y%8==0 )
37
          {
38
            if (x<64)                
39
              lcd_write_data(data,CHIP1);            
40
            else                  
41
              lcd_write_data(data,CHIP2);          
42
          }
43
          else
44
          #endif
45
          {
46
            for (bit=0;bit<8;bit++)
47
            {
48
              if ((data&(1<<bit))!=0)
49
               lcd_set_pixel(x,cursor_y+page*8+bit,color);
50
            }
51
          }
52
        }      
53
        
54
        #ifdef FASTTEXT
55
        if(cursor_y%8==0)
56
        {
57
          if (x<64)                
58
            lcd_write_data(0,CHIP1);            
59
          else                  
60
            lcd_write_data(0,CHIP2);        
61
        }
62
        #endif
63
      }      
64
      cursor_x += font_char_width(font,chr)+1;
65
66
67
    }
68
  }
69
}
70
71
// ------------------------------------
72
// fills an rectangle with given color
73
// ------------------------------------
74
75
void lcd_fill_rect(uint8_t x,uint8_t y,uint8_t width,uint8_t height,uint8_t color)
76
{
77
  uint8_t cnt_x,cnt_y;
78
    for (cnt_y=y;cnt_y<y+height;cnt_y++)        // fill screen using set_pixel (slow) but needs less memory
79
      for (cnt_x=x;cnt_x<x+width;cnt_x++)
80
        lcd_set_pixel(cnt_x,cnt_y,color);
81
82
}

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.