Grafik Lcd'de doğru çizmek,

Başlatan fatihvelid, 05 Temmuz 2007, 13:15:53

fatihvelid

Merhaba arkadaşlar, KS108 için driver yazıyorum. Lcd'de doğru çizen ve istediğim piksele nokta koyan fonksiyon yazmak istiyorum.

Nasıl yapabileceğim konusunda yardımcı olabilirmisiniz ? Bu konuda  örnek var mı ?
Kainatta her canlı "DNA" diliyle yazılmış bir programdır...

birumher

Doğru çizmek için Bresenham algoritması kullanabilirsin.

http://tr.wikipedia.org/w/index.php?title=Bresenham%27%C4%B1n_%C3%A7izgi_algoritmas%C4%B1&oldid=1761138

adresinde algoritmanın detaylarını bulabilirsin.

Aşağıda da Picc ile yapılmış örnek var.
glcd_pixel() fonksiyonunu yazarsan bunu aynen bu şekilde kullanabilirsin.

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
// Purpose:       Draw a line on a graphic LCD using Bresenham's
//                line drawing algorithm
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                color - ON or OFF
// Dependencies:  glcd_pixel()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
void glcd_line(int x1, int y1, int x2, int y2, int1 color)
{
  signed int  x, y, addx, addy, dx, dy;
  signed long P;
  int i;
  dx = abs((signed int)(x2 - x1));
  dy = abs((signed int)(y2 - y1));
  x = x1;
  y = y1;
  if(x1 > x2)
    addx = -1;
  else
    addx = 1;
  if(y1 > y2)
    addy = -1;
  else
    addy = 1;
  if(dx >= dy)
  {
    P = 2*dy - dx;
    for(i=0; i<=dx; ++i)
    {
      glcd_pixel(x, y, color);
      if(P < 0)
      {
        P += 2*dy;
        x += addx;
      }
      else
      {
        P += 2*dy - 2*dx;
        x += addx;
        y += addy;
      }
    }
  }
  else
  {
    P = 2*dx - dy;
    for(i=0; i<=dy; ++i)
    {
      glcd_pixel(x, y, color);
      if(P < 0)
      {
        P += 2*dx;
        y += addy;
      }
      else
      {
        P += 2*dx - 2*dy;
        x += addx;
        y += addy;
      }
    }
  }
}
Birkan.Herguner

fatihvelid

İlginiz için teşekkür ederim.

İstediğimiz X,Page piksel'ine ekrandaki görüntü üzerinden nasıl nokta koyabilirim?
Kainatta her canlı "DNA" diliyle yazılmış bir programdır...

fatihvelid

Grafik LCD'nin RAM'ini belleğe kopyalayıp ( 1024 byte )  grafiksel bütün işlemleri bellekte yapsam ve grafik lcd'ye geri yazsam bu yöntem nasıl olur.

Ayrıca yatay ve dikey çizgileri nasıl çizebilirim. Yukarıdaki algoritmayı kullanmadan
Kainatta her canlı "DNA" diliyle yazılmış bir programdır...

birumher

Alıntı yapılan: "fatihvelid"Grafik LCD'nin RAM'ini belleğe kopyalayıp ( 1024 byte )  grafiksel bütün işlemleri bellekte yapsam ve grafik lcd'ye geri yazsam bu yöntem nasıl olur.

Ayrıca yatay ve dikey çizgileri nasıl çizebilirim. Yukarıdaki algoritmayı kullanmadan

Her seferinde 1024 byte veriyi LCD ye göndereceksen pek mantıklı değil gibi geldi bana. Sadece değişenleri göndereceksen olabilir ancak çarpışma testi vs yapmayacaksan neden RAM e kopyalamaya ihtiyacın olsun ki.

Yatay veya dikey çizgi çekmek kolay.

Yatay çizgi için

örneğin başlangıç koordinatları x1,y1 bitiş koordinatları x2,y2 olsun zaten y1 ve y2 eşit olmak zorunda bir döngü kuracaksın x1 den x2 ye kadar

for(i=x1; i<=x2; ++i)
{
 glcd_pixel(i, y1, color);
}

diyeceksin burada x1 x2 den küçük olmalı. Değilse sıralarını değiştirirsin.

dikey çizgi çekmek içinse

for(i=y1; i<=y2; ++i)
{
 glcd_pixel(x1, y, color);
}

diyeceksin. Burada da y1 < y2 olmalı.
Birkan.Herguner

CLR

@fatihvelid

GLCD'de 2 tane KS0108 var.
Her chip 8 sayfa,64 sutun'u kontrol eder.
Dolayısıyla 2 tanesi 8 sayfa,128 sutun'u kontrol eder.

Herhangi bir pixel'i yakmak istiyorsan, önce ilgili işlemciyi seçeceksin
sonra pixel sangi sayfadaysa, sayfa kodunu göndereceksin, pixel hangi sutundaysa sutun kodunu göndereceksin, ve son olarak pixel, hangi bit ise
onu 1 yapacaksın diğer 7 bit 0 olacak.

Sayfa ve sutun kodları nedir ve nasıldır diyorsan, GLCD'nin datasheet'ini incele. İçinde ks0108 bulunan tüm datashetlerden faydalanabilirsin.
Glcd'nin bacak bağlantıları dışında farklılık olmaz.

Kolay gelsin.
Knowledge and Experience are Power

mesmert

Alıntı yapılan: "fatihvelid"İlginiz için teşekkür ederim.

İstediğimiz X,Page piksel'ine ekrandaki görüntü üzerinden nasıl nokta koyabilirim?


GLCD'ler decimal 184 başlayıp 191 de biter ve toplam 8 sayfadır. senin yapacağın GLCD sayfa bilgisini gönderip daha sonra hangi pixel aftif olmasını istiyorsan hangi bölgede ise onun cipini on yapıp daha sonra pixel değerini gönderiyorsun.

fatihvelid

İlk çalıştırdığımda çok kısa süre için ekran gidip geliyor. Nedendir acaba.

Ayrıca GLCD'nin RAM'ini okurken bir sorunla karşılaşıyorum. Okumuyor ve hep 0 dönüyor sanırım. Yazdığım kod aşağıda. Bir hata mı var?

BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)  
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
 GLCD_Data_TRIS = 0xFF;  
 GLCD_RW = 1;
 GLCD_E = 1;
 Delay1KTCYx(1);
 GLCD_E = 0;
 Delay1KTCYx(1);
 GLCD_E = 1;
 Delay1KTCYx(1);
 Data = GLCD_Data_PORT;
 GLCD_E = 0;  
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 GLCD_Data_TRIS = 0x00;  
 GLCD_RW = 0;
return Data;
}
Kainatta her canlı "DNA" diliyle yazılmış bir programdır...

mesmert

CCS bilmediğim için vereceğim fikir belki işine yarar; KS0108 GLCD okurken dikkat etmen gereken kısım lcd ekran iki ayrı çipten oluştuğu için ilk önce birinci chip aktif yapıp okuyacaksın sonra ise birinci chip off yapıp ikinci chip okuyacaksın

fatihvelid

CCS kullanmıyorum. Programı C18 ile geliştiriyorum.Kendi oluşturduğum yapıları kullanıyorum.
Yukarıdaki programda, BYTE GlcdRead(CS _cs)  fonksiyonunu çağırmadan önce PAGE ve X eksenini ayarlıyor. Ve ardından CS'lerden sadece birisini aktif yapıyor.

RW = 1 olduğunda E'nin düşen kenarında veriyi almaya çalışıyor.
Kainatta her canlı "DNA" diliyle yazılmış bir programdır...

CLR

Okuma ve yazmada bilmen gereken en önemli noktalar şunlar

1) GLCD'ye Yazma yapacaksan E'nin düşen kenarında yazılır
   GLCD'den bir data okuyacaksan E=1 iken okunur

2) Data okuyacakken veya yazacakken  LCD meşgul mu değilmi bilmelisin yani ilk önce busy flag okunur.


Kolay gelsin
Knowledge and Experience are Power

fatihvelid

Alıntı yapılan: "eemkutay"Okuma ve yazmada bilmen gereken en önemli noktalar şunlar

1) GLCD'ye Yazma yapacaksan E'nin düşen kenarında yazılır
   GLCD'den bir data okuyacaksan E=1 iken okunur

2) Data okuyacakken veya yazacakken  LCD meşgul mu değilmi bilmelisin yani ilk önce busy flag okunur.


Kolay gelsin


Busy Flag'ı nasıl okuyabilirim. Ve işlemler arasına ne kadar gecikme koymam gerekiyor.


Aşağıdaki kod'da sorun olmasa gerek.


BYTE GlcdRead(CS _cs)
{
BYTE Data;
if(_cs == CS2)
GLCD_CS2 = TRUE;
else
GLCD_CS1 = TRUE;
GLCD_Data_TRIS = 0xFF;
GLCD_RW = 1;
GLCD_E = 1;
Delay1KTCYx(1);
GLCD_E = 0;
Delay1KTCYx(1);
GLCD_E = 1;
Delay1KTCYx(1);
Data = GLCD_Data_PORT;
GLCD_E = 0;
GLCD_CS1 = FALSE;
GLCD_CS2 = FALSE;
GLCD_Data_TRIS = 0x00;
GLCD_RW = 0;
return Data;
}

Kolay Gelsin
Kainatta her canlı "DNA" diliyle yazılmış bir programdır...

CLR

Karakter LCD'deki gibi araya delay koyarak bu iş çözülmez. Çünkü GLCD üreticisi, "GLCD'nin işlemleri şu kadar zaman alır " gibi kesin bilgiler vermiyorlar dolayısıyla  glcd içindeki status registerinin 7 biti busy flag'dir. Bu flag kontrol edilir. Busy flag 0 ise data yazabilir veya okuyabilirsin.

Arada gereksiz enable'ların vardı kaldırdım

// Bu kod data okumak içindir status'u okumaz, statusu okumak için 
// diğer kısımları kullanmalısın ( // ile yazdığım)

BYTE GlcdRead(CS _cs)
{
  BYTE Data;
  if(_cs == CS2)
  GLCD_CS2 = TRUE;
  else
  GLCD_CS1 = TRUE;
// GLCD_RS=0;                   // busy için
  GLCD_RS=1;
  GLCD_RW = 1; 
  GLCD_E=1;

  GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.

// oku:
  Data = GLCD_Data_PORT;    
//  if(Data&&0x80)                // 7.bit testi yapıyoruz
//  goto    oku;                     // LCD meşgul
 
  GLCD_E = 0;
  GLCD_CS1 = FALSE;
  GLCD_CS2 = FALSE;
  GLCD_Data_TRIS = 0x00;
  GLCD_RW = 0;
  return Data;
} 
  
Knowledge and Experience are Power

fatihvelid

Alıntı yapılan: "eemkutay"
// Bu kod data okumak içindir status'u okumaz, statusu okumak için 
// diğer kısımları kullanmalısın ( // ile yazdığım)

BYTE GlcdRead(CS _cs)
{
  BYTE Data;
  if(_cs == CS2)
  GLCD_CS2 = TRUE;
  else
  GLCD_CS1 = TRUE;
// GLCD_RS=0;                   // busy için
  GLCD_RS=1;
  GLCD_RW = 1; 
  GLCD_E=1;

  GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.

// oku:
  Data = GLCD_Data_PORT;    
//  if(Data&&0x80)                // 7.bit testi yapıyoruz
//  goto    oku;                     // LCD meşgul
 
  GLCD_E = 0;
  GLCD_CS1 = FALSE;
  GLCD_CS2 = FALSE;
  GLCD_Data_TRIS = 0x00;
  GLCD_RW = 0;
  return Data;
} 
  


Düzenleyip aşağıdaki hale getirdim. Ama yine biryerlerde sorun var. PIC 40 MHZ'de çalışıyor. Hızdan kaynaklanan bir sorun olabilir mi ?

Yanlışım varsa düzeltirmisiniz ?

Alıntı Yap


BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
 GLCD_RW = 1;
 GLCD_DI = 1;
 GLCD_E=1;
 GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.
 Glcd_Wait_Busy();  
 _asm
 nop
 nop
 nop
 nop
 nop
 _endasm
 Data = GLCD_Data_PORT;    
 GLCD_E = 0;
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 return Data;
}

void Glcd_Wait_Busy(void)
{
BYTE status;
GLCD_DI = 0;
GLCD_RW = 0;
GLCD_Data_TRIS = 0xff;
_asm
nop
nop
nop
_endasm

while(1)
{
GLCD_E = 1;
_asm
nop
nop
nop
_endasm
status = GLCD_Data_PORT;
if ((status & 0x80) == 0)
break;
_asm
nop
nop
nop
_endasm
}
GLCD_Data_TRIS = 0x00;
GLCD_RW = 0;
}

İlgileriniz için teşekkürler. Kolaya gelsin
Kainatta her canlı "DNA" diliyle yazılmış bir programdır...

CLR

Alıntı Yap

BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
 GLCD_RW = 1;
 GLCD_DI = 1;
 GLCD_E=1;
 GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.
 Glcd_Wait_Busy();              
 _asm
 nop
 nop
 nop
 nop
 nop
 _endasm
 Data = GLCD_Data_PORT;    
 GLCD_E = 0;
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 return Data;
}

void Glcd_Wait_Busy(void)
{
BYTE status;
GLCD_DI = 0;
GLCD_RW = 0;
GLCD_Data_TRIS = 0xff;
_asm
nop
nop
nop
_endasm

while(1)
{
GLCD_E = 1;
_asm
nop
nop
nop
_endasm
status = GLCD_Data_PORT;
if ((status & 0x80) == 0)
break;
_asm
nop
nop
nop
_endasm
}
GLCD_Data_TRIS = 0x00;
GLCD_RW = 0;
}

İlgileriniz için teşekkürler. Kolaya gelsin[/quote]

Elindeki Glcd'nin datasheet'in deki zamanlama tablosunu ve diyagramını incelemelisin. 40Mhz çok yüksek hız, bir komut 100ns , programda hatalar  var ve zamanlama problemin olmaması için dediğim gibi zaman haberleşme diyagramını incele , benim kullandığım glcd, hy12864 ve clock puls'i en az 450ns diyor ve ben 20mhz'de 3 tane nop atıyorum (600ns) herşey ok.

Zamanlama diyagramındaki zamanlardan biraz daha yavaş çalıştırırsan , sorun olmayacaktır.

Programında hatalar var, busy test fonksiyonun kullanım yeri hatalı,
ilk önce busy testi yapılır sonra read işlemi yapılır, aşağıdaki gibi

Glcd_Wait_Busy();    // lcd meşgul mu? meşgul değilse aşağı satıra geçer
 Glcd_Read(1);          // Daha önce girdiğin adresi 1. chip'ten okur

// read programında hata vardı düzeltildi, aşağıdaki gibi olacak ama yine
// datasheet'ten zamanlamaları kontrol etmelisin bu nedenle nop'lara
// dokunmadım

BYTE GlcdRead(CS _cs) 
{ 
  BYTE Data; 
  if(_cs == CS2) 
  GLCD_CS2 = TRUE; 
  else 
  GLCD_CS1 = TRUE; 
  GLCD_RW = 1;                   // datasheet'e göre bu seviye aralarına 
  GLCD_DI = 1;                    // nop'lar gerekebilir
  GLCD_E=1; 
  GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.     
  _asm
  nop
  nop                                  
  nop                                    // en az nop için dahasheet'e bakmalısın
  nop
  nop
  _endasm
  Data = GLCD_Data_PORT;    
  GLCD_E = 0; 
  GLCD_CS1 = FALSE; 
  GLCD_CS2 = FALSE; 
  return Data; 
} 

// burada her iki chip busy mi test ediliyor istersen adrese göre
// yapabilirsin

void Glcd_Wait_Busy(void)
{
GLCD_CS1=1;                          //1.chip on, diğeri zaten off
busy_test( );                            // busy flag=0 oluncaya kadar bekle
GLCD_CS1=0;
GLCD_CS2=1;                         //2.chip on, diğeri  off
busy_test( );                           // busy flag=0 oluncaya kadar bekle
}

// tek chip busy mi test ediyor
void busy_test(void)
{
BYTE status;
GLCD_DI = 0;                          // komut modu
GLCD_RW = 1;                        // okuma modu
GLCD_E = 1;                           // data okuyacağız, E=1
GLCD_Data_TRIS = 0xFF;        // portlar giriş
_asm
nop
nop
nop
_endasm

while(1)
{
_asm
nop
nop
nop
_endasm
status = GLCD_Data_PORT;        // portu oku
if (status & 0x80)                       // busy flag =0 ise çık
break;
_asm
nop
nop
nop
_endasm
}
GLCD_Data_TRIS = 0x00;          // port çıkış
GLCD_E = 0;                             // E=0
}
Knowledge and Experience are Power