#include <mega32.h>
#include <spi.h>
#include <string.h>
#include <delay.h>
#include <stdio.h>
#include <Font.h>

#define DISP_W 132
#define DISP_H 176
#define CHAR_W 8  //ширина 
#define CHAR_H 14 //высота

// сопоставление выводов дисплея и микроконтроллера
#define RESET        PORTB.6
#define CS           PORTB.3
//#define alarm        PORTB.0
// тактовый и информационный вход дисплея
// подключены к аппаратному SPI микроконтроллера

// определение основных цветов
// просто для удобства;)
#define BLACK 0x0000
#define RED   0xf800
#define GREEN 0x07e0
#define BLUE  0x001f
#define WHITE 0xffff
#define ORANGE 0xfca0
#define sky 0x54fb
#define yellow 0xDEE0
#define orange 0xAB00
#define pink 0xF97F
#define brown 0x8200
#define grey 0x8410
#define violet 0x91D4 

unsigned int i=0, j=0;
unsigned int counter=0;


// цвет фона и текста по умолчанию
unsigned int textcolor=BLUE;
unsigned int bgcolor=WHITE;


// запись одного байта в дисплей
void lcd_write8(char dat)
{
  spi(dat);   //1 байт в регистр данных SPI
}

// запись двух байт
void lcd_write(unsigned int dat)
{
  lcd_write8(dat>>8);
  lcd_write8 (dat);
}

// дергаем выводом CS для обозначения конца передачи данных
void lcd_c(void)
{
  CS= 1;
  #asm("nop")
  CS= 0;
}

// выбор регистра в контроллере дисплея
void lcd_reg(char register_name)
{
  lcd_write8(0x74);  // стартовый байт на передачу команды
  lcd_write(register_name);
  lcd_c();
}

// отправка двух байт в графическую память дисплея
void lcd_dat8(char register_dat1, char register_dat2)
{
  lcd_write8(0x76);  // стартовый байт на запись данных
  lcd_write8(register_dat1);
  lcd_write8(register_dat2);
  lcd_c();
  
}

// то же самое, но из 16-и битной переменной
void lcd_dat(unsigned int data)
{
  lcd_write8(0x76);  // стартовый байт на запись данных
  lcd_write(data);
  lcd_c();
}

// программа инициализации дисплея
void lcd_init_c(void)
{
  RESET=0;
  CS=1;
  delay_ms(1);
  RESET=1;
  
  delay_ms(10);
  
  CS=0;
  
  delay_ms(50);
  lcd_reg(0x00);lcd_dat(0x0001);

  lcd_reg(0x03);lcd_dat(0x000c);

  delay_ms(100);
  lcd_reg(0x0d);lcd_dat(0x0616);

  lcd_reg(0x01);lcd_dat(0x0215);
  
  delay_ms(150);  
  lcd_reg(0x07);lcd_dat(0x0037);
    
  CS= 1;
}

// заливка дисплея цветом color
void fill_screen(unsigned int color)
{
  
  CS= 0;  // select display
  
  lcd_reg(0x16);lcd_dat(0x8300);
  lcd_reg(0x17);lcd_dat(0xAF00);
  lcd_reg(0x21);lcd_dat(0x0000);
  lcd_reg(0x22);lcd_write8(0x76);  
  
  // start data transmission  
  for (i=0; i<DISP_H; i++)
  {
   for(j=0;j<DISP_W;j++)
   {
    lcd_write(color);
   }
  }  

  CS= 1;  // deselect display    
}

// поместить символ в графическую память дисплея
void put_char(char x, char y, char c, unsigned int color, char rot, char m)
{
  char h,ch,p,mask;

  CS= 0;
  
  switch(rot)
  {
    default:
    case 0:
      lcd_reg(0x05);lcd_dat(0x0038);
      lcd_reg(0x17);lcd_dat8(x+CHAR_W*m-1, x);
      lcd_reg(0x16);lcd_dat8(y+CHAR_H*m-1, y);
      lcd_reg(0x21);lcd_dat8(x,y);
      lcd_reg(0x22);
      lcd_write8(0x76);
      break;
    case 1:
      lcd_reg(0x05);lcd_dat(0x0030);
      lcd_reg(0x16);lcd_dat8(x+CHAR_W*m-1, x);
      lcd_reg(0x17);lcd_dat8(y+CHAR_H*m-1, y);
      lcd_reg(0x21);lcd_dat8(y,x);
      lcd_reg(0x22);
      lcd_write8(0x76); 
      break;
  }
     if (c>127) {
     c=c-57;          //убираем отсутствующую часть таблицы ASCII
     };
     
   for (h=0; h<CHAR_H*m; h++) // every column of the character
  {
       if (rot==1)
       ch=ascii_tab[ c-32 ][h/m];
       else
       ch=ascii_tab[ c-32 ][CHAR_H-h/m];
   
        mask=0x80;
     for (p=0; p<CHAR_W; p++)  // write the pixels
     {
       if (ch&mask)
       {
           lcd_write(color);
         
           if(m==2) {
           lcd_write(color);
           } 
           
           if (m==3) {
           lcd_write(color);
           lcd_write(color);
           }
           
           if (m==4) {
            lcd_write(color);
            lcd_write(color);
            lcd_write(color);
           }           
       }
      else
       {
            lcd_write(bgcolor);
            
            if(m==2) {
            lcd_write(bgcolor);
            } 
            
            if (m==3) {
            lcd_write(bgcolor);
            lcd_write(bgcolor);
            } 
            
            if (m==4) {
            lcd_write(bgcolor);
            lcd_write(bgcolor);
            lcd_write(bgcolor);
            }
       }
       mask=mask/2;
     }
  }
   
CS= 1;  // deselect display   

}

// записать строку, начиная с координат x, y, цветом color и ориентацией orient
// если orient=0, то горизонтально, если =1, то вертикально
void put_string(unsigned char x, unsigned char y, char *str, unsigned int color, unsigned char orient, char m)
{
  j=0;
  while (j<strlen(str))
  {
    put_char(x+j*CHAR_W*m,y,str[j],color,orient,m);   //  0 deg. rotated
    j++;
  }
}


//=======================================================================================
//           Процедура вывода точки
//=======================================================================================
// рисуем пиксел в заданной точке (x,y), с цветом color
void lcd_pixel (int x, int y, unsigned int color)
 {
    CS=0;
      
      lcd_reg(0x17);lcd_dat8(DISP_H-x,DISP_H-x);
      lcd_reg(0x16);lcd_dat8(y,y);
       
      lcd_reg(0x21); lcd_dat8(DISP_H-x,y);    //Записываем в регистр позицию
      lcd_reg(0x22); lcd_write8(0x76);        // стартовый байт на запись данных (DISP_H-x,y)
   
      lcd_write(color);
     
    CS=1;
 }
 //======================================================================================
//   Процедура вывода картинки
//=======================================================================================
//  lcd_picture(10,14,32,16,img_hard);
//  вывести картинку с началом по х=10:у=14 с размером по х=32:у=16 из массива img_hard[]
//=======================================================================================
void lcd_picture(char x, char y, char w, char h, char rot, flash unsigned int *pic)
  {
    unsigned int i,j;
    CS=0;
     if (rot==1)
    {
      lcd_reg(0x05);lcd_dat(0x0030);
      lcd_reg(0x16);lcd_dat8(x+h-1,x);
      lcd_reg(0x17);lcd_dat8(y+w-1,y);
      lcd_reg(0x21);lcd_dat8(x,y);
      lcd_reg(0x22);lcd_write8(0x76);
      //Пишем точку
      for(i=0; i<h; i++)              //i увеличиваем от 0 до h(176)
      for (j=0; j<w; j++)             // j уменьшаем от0 до w(132)
      lcd_write(pic[(i*w)+j]);     // и считаем позицию в массиве i*w+j 
    }
     else 
    {
      lcd_reg(0x05);lcd_dat(0x0038);
      lcd_reg(0x16);lcd_dat8(y+w-1,y); 
      lcd_reg(0x17);lcd_dat8(x+h-1,x);
      lcd_reg(0x21);lcd_dat8(y,x);
      lcd_reg(0x22);lcd_write8(0x76);
      //Пишем точку
      for(i=0; i<h; i++)              //i увеличиваем от 0 до h(176)
      for (j=0; j<w; j++)             // j уменьшаем от0 до w(132)
      lcd_write(pic[(i*w)+j]);     // и считаем позицию в массиве i*w+j    
    };
                 
     CS=1;
  }
//=======================================================================


//=======================================================================
 void lcd_scroll(char h_area)
{
        CS=0;                    // select display, low
        lcd_reg(0x11);
        lcd_dat8(0,0+h_area);        // scroll vertical 2 pix
        lcd_reg(0x07);
        lcd_dat8(0x02, 0x37);
        CS=1;                        // deselect display, high
}

//==========================================================================================
//      Процедура заполнение цветом области
//==========================================================================================
// fill_area(10,14,32,16,BLUE); 
// Нарисовать прямоугольник с началом по х=10:у=14 с размером по х=32:у=16 цветом BLUE
void fill_area( char x1, char x2, char y1, char y2,int color)
    {
     int i;
     char w,h;
     
      lcd_reg(0x05);lcd_dat(0x0030);
      lcd_reg(0x16);lcd_dat8(y2,y1);
      lcd_reg(0x17);lcd_dat8(x2,x1);
      lcd_reg(0x21);lcd_dat8(x1,y1);
      lcd_reg(0x22);lcd_write8(0x76);
      //Пишем точку
      w=x2-x1+1;h=y2-y1+1;
     for (i=0;i<w*h;i++) 
     {
       lcd_write(color);     
     };                             
    }