#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#include "font5x7.h"
#include "font.h"




typedef unsigned char	U08;			/* data type definition */
typedef   signed char	S08;
typedef unsigned int	U16;
typedef   signed int	S16;
typedef unsigned long	U32;
typedef   signed long	S32;


unsigned char ScreenMode = 'P';			// screen mode(P=portrait, L=landscape)
unsigned char LineLimit = 30;			// character length of line (30 or 40)
unsigned char KoreanBuffer[32] = {0};		// 32 byte Korean font buffer
unsigned char xcharacter, ycharacter;		// xcharacter(0-29), ycharacter(0-39) for portrait
						// xcharacter(0-39), ycharacter(0-29) for landscape
unsigned int  foreground, background;		// foreground and background color
unsigned char cursor_flag = 0;			// 0 = cursor off, 1 = cursor on
unsigned char xcursor, ycursor;			// cursor position
unsigned int  cursor;				// cursor color
unsigned char outline_flag = 0;			// 0 = outline off, 1 = outline on
unsigned int  outline;				// outline color



//#define LCDr  PORTD_Bit2
/*
#define BIT(x) (1<<(x))
void  PORTD_L(int i)  {PORTD = PORTD & ~BIT(i);}
void  PORTD_H(int i)  {PORTD = PORTD |  BIT(i);}

#define  RST_L  PORTD &= ~0x04	// set PD5-/RESET line Low(reset)
#define  RST_H	PORTD |=  0x04	// set PD5-/RESET line High
*/

#define White		0xFFFF			/* 16 bit 8 color data */
#define Black		0x0000
#define Red		0xF800
#define Green		0x07E0
#define Blue		0x001F
#define Yellow		0xFFE0			// Yellow = Red + Green
#define Cyan		0x07FF			// Cyan = Green + Blue
#define Magenta		0xF81F			// Magenta = Red + Blue
#define Brown		0xA145
#define Khaki		0xF731
#define Olive		0x8400
#define Orange		0xFD20
#define Pink		0xFB56
#define Purple		0x8010
#define Silver		0xC618
#define Violet		0xEC1D
#define Transparent	0x0821

#define BLACK        0x0000		// RRRRR GGGGGG BBBBB   => 565
#define WHITE        0xffff
#define YELLOW       0xffe0
#define DARK_YELLOW  YELLOW & GRAY09
#define RED          0xf800
#define DARK_RED     RED & GRAY09
#define GREEN        0x07e0
#define DARK_GREEN   GREEN & GRAY09
#define BLUE         0x001f
#define DARK_BLUE    BLUE & GRAY09
#define CYAN         0x07ff
#define MAGENTA      0xf81f

#define GRAY01       0xef7d
#define GRAY02       0xe71c
#define GRAY03       0xd69a
#define GRAY04       0xc618
#define GRAY05       0xb596
#define GRAY06       0xa514
#define GRAY07       0x9492
#define GRAY08       0x738e
#define GRAY09       0x630c
#define GRAY10       0x528a
#define GRAY11       0x39e7
#define GRAY12       0x3186
#define GRAY13       0x2104
#define GRAY14       0x1082



#define MAX_DOT      76800 // 240 X RGB X 400 dot
#define X_MAX_PIXEL  320
#define Y_MAX_PIXEL  240

// 화면 표시 방법
#define		SCREEN_COLUMN_SET	0			// 가로방향 표시모드 왼쪽상단(0,0) 
#define		SCREEN_ROW_SET		1			// 세로방향 표시모드 왼쪽상단(0,0) 


#define		SCREEN_COLUMN_X	319			// 가로방향 표시모드시 X축 최대값
#define		SCREEN_COLUMN_Y	239			// 가로방향 표시모드시 Y축 최대값
#define		SCREEN_ROW_X		239			// 세로방향 표시모드시 X축 최대값
#define		SCREEN_ROW_Y		319			// 세로방향 표시모드시 Y축 최대값
  
#define   DATA_LCD_PORT  PORTF
  
#define   LCD_RD_H    PORTA |= _BV(4);  // RD H
#define   LCD_RD_L  	PORTA &= ~_BV(4); // 
#define   LCD_WR_H  	PORTA |= _BV(5);  //
#define   LCD_WR_L    PORTA &= ~_BV(5); // 
#define   LCD_RS_H  	PORTA |= _BV(6);  //
#define   LCD_RS_L    PORTA &= ~_BV(6); // 
#define   LCD_CS_H  	PORTA |= _BV(7);  //
#define   LCD_CS_L    PORTA &= ~_BV(7); // 
                
#define   LCD_RST_H	  PORTA |= _BV(2);  //reset H
#define   LCD_RST_L   PORTA &= ~_BV(2);// reset L
#define   LCD_BL_H	  PORTA |= _BV(3);  //백라이트  H
#define   LCD_BL_L    PORTA &= ~_BV(3);// 백라이트 L
extern prog_uchar bird0[2960];	
	
 //변수 선언
int screen_mode = SCREEN_COLUMN_SET;				// 화면 표시방식 저장
int screen_xmax = SCREEN_COLUMN_X;				// 가로면 최대값
int screen_ymax = SCREEN_COLUMN_Y;				// 세로면 최대값
unsigned screen_color = RED;				// 문자색 설정  WHITE;

unsigned screen_bkcolor = BLACK;				// 바탕색 설정
int screen_curx = 0;						// X 좌표 저장
int screen_cury = 0;						// Y좌표 저장

const unsigned int line[1]= {YELLOW};
const unsigned int basic_color[8] = {BLACK, WHITE, RED, YELLOW, CYAN, BLUE, GREEN, MAGENTA};
const unsigned int gray16[16]= {0x0000, 0x1082, 0x2104, 0x3186, 0x39e7, 0x528a, 0x630c, 0x738e
                              , 0x9492, 0xa514, 0xb596, 0xc618, 0xd69a, 0xe71c, 0xef7d, 0xffff};

//unsigned int d1,d1_1,d2,d2_1;

void delay_us(unsigned char time_us)		// delay for us	
{ register unsigned char i;

  for(i = 0; i < time_us; i++)			// 4 cycle +
    { asm volatile(" PUSH  R0 ");		// 2 cycle +
      asm volatile(" POP   R0 ");		// 2 cycle +
   	  asm volatile(" PUSH  R0 ");		// 2 cycle +
      asm volatile(" POP   R0 ");		// 2 cycle +
	    asm volatile(" PUSH  R0 ");		// 2 cycle +
      asm volatile(" POP   R0 ");		// 2 cycle = 16 cycle = 1 us for 16MHz
    }
}

void delay_ms(unsigned int time_ms)		// delay for ms	
{ register unsigned int i;

  for(i = 0; i < time_ms; i++)
    { delay_us(250);
      delay_us(250);
      delay_us(250);
      delay_us(250);
    }
}


void LCD_WR_REG16(unsigned int index)//
{
    LCD_CS_L;     LCD_RS_L;  LCD_RD_H;   LCD_WR_H;
   
  PORTF = index >> 8;				// write high byte
  PORTC = index & 0x00FF;			// write high + low byte 0x00FF

 LCD_WR_L;   LCD_WR_H;      LCD_CS_H;
  
/*
 //8bit
    LCD_CS_L;     LCD_RS_L;  LCD_RD_H;   LCD_WR_H;	
   DATA_LCD_PORT=index>>8; 
   LCD_WR_L;	LCD_WR_H;
   DATA_LCD_PORT=index&0XFF; 
   LCD_WR_L;   LCD_WR_H;      LCD_CS_H;
*/

}

void LCD_WR_DATA16(unsigned int data)//
{
        LCD_CS_L;   LCD_RS_H;	LCD_RD_H;    LCD_WR_H;
  PORTF = data >> 8;				// write high byte
  PORTC = data & 0x00FF;			// write high + low byte 0x00FF

     LCD_WR_L;   LCD_WR_H;   LCD_CS_H;

  
  /*
   LCD_CS_L;   LCD_RS_H;	LCD_RD_H;    LCD_WR_H;
     DATA_LCD_PORT=data>>8;
     LCD_WR_L;   LCD_WR_H; 
     DATA_LCD_PORT=data&0XFF; 
     LCD_WR_L;   LCD_WR_H;   LCD_CS_H;

  */
}

void LCD_WR_REG(unsigned int index,unsigned int data)
{
     LCD_WR_REG16(index);     LCD_WR_DATA16(data);
}


void TFT_SET()
{
/*
	PORTA = 0x00;	
 	PORTC = 0x00;
 	PORTF = 0x00;
 	delay_ms(120);   
 	PORTA = 0xFF;	   
 	PORTC = 0xFF;	   
 	PORTF = 0xFF;  
*/
	delay_us(1);
  LCD_BL_H;

//////////   ILI9328_      /////////////////////

//************* Reset LCD Driver ****************//

//  RST_H;  	WR_H;	CS_H; 	RS_H;  	RD_H;
 
    LCD_RST_H;    delay_ms(1); 
    LCD_RST_L;    delay_ms(10);  
    LCD_RST_H;    delay_ms(50);  
//************* Start Initial Sequence **********//
//LCD_WR_REG(0x0001);lcd_data(0x0100); // set SS and SM bit

LCD_WR_REG(0x0001,0x0000); // set SS and SM bit
                
LCD_WR_REG(0x0002,0x0700); //   0700  set 1 line inversion
LCD_WR_REG(0x0003,0x1030); // set GRAM write direction and BGR=1.
//0010
//LCD_WR_REG(0x0003,0x1028); // set GRAM write direction and BGR=1.

LCD_WR_REG(0x0004,0x0000); // Resize register
LCD_WR_REG(0x0008,0x0207); // set the back porch and front porch
LCD_WR_REG(0x0009,0x0000); // set non-display area refresh cycle ISC[3:0]
LCD_WR_REG(0x000A,0x0000); // FMARK function
LCD_WR_REG(0x000C,0x0000); // RGB interface setting
LCD_WR_REG(0x000D,0x0000); // Frame marker Position
LCD_WR_REG(0x000F,0x0000); // RGB interface polarity
//*************Power On sequence ****************//
LCD_WR_REG(0x0010,0x0000); // SAP);lcd_data(BT[3:0]);lcd_data(AP);lcd_data(DSTB);lcd_data(SLP);lcd_data(STB
LCD_WR_REG(0x0011,0x0007); // DC1[2:0]);lcd_data(DC0[2:0]);lcd_data(VC[2:0]
LCD_WR_REG(0x0012,0x0000); // VREG1OUT voltage
LCD_WR_REG(0x0013,0x0000); // VDV[4:0] for VCOM amplitude
LCD_WR_REG(0x0007,0x0001);
delay_ms(200); 
LCD_WR_REG(0x0010,0x1290); // SAP);lcd_data(BT[3:0]);lcd_data(AP);lcd_data(DSTB);lcd_data(SLP);lcd_data(STB
LCD_WR_REG(0x0011,0x0227); // DC1[2:0]);lcd_data(DC0[2:0]);lcd_data(VC[2:0]
delay_ms(50); 
LCD_WR_REG(0x0012,0x001A); // Internal reference voltage= Vci;
delay_ms(50); 
LCD_WR_REG(0x0013,0x1800); // Set VDV[4:0] for VCOM amplitude
LCD_WR_REG(0x0029,0x0028); // Set VCM[5:0] for VCOMH
LCD_WR_REG(0x002B,0x000C); // Set Frame Rate
delay_ms(50); 
LCD_WR_REG(0x0020,0x0000); // GRAM horizontal Address
LCD_WR_REG(0x0021,0x0000); // GRAM Vertical Address
// ----------- Adjust the Gamma Curve ----------//
LCD_WR_REG(0x0030,0x0000);
LCD_WR_REG(0x0031,0x0305);
LCD_WR_REG(0x0032,0x0003);
LCD_WR_REG(0x0035,0x0304);
LCD_WR_REG(0x0036,0x000F);
LCD_WR_REG(0x0037,0x0407);
LCD_WR_REG(0x0038,0x0204);
LCD_WR_REG(0x0039,0x0707);
LCD_WR_REG(0x003C,0x0403);
LCD_WR_REG(0x003D,0x1604);
//------------------ Set GRAM area ---------------//
LCD_WR_REG(0x0050,0x0000); // Horizontal GRAM Start Address
LCD_WR_REG(0x0051,0x00EF); // Horizontal GRAM End Address
LCD_WR_REG(0x0052,0x0000); // Vertical GRAM Start Address
LCD_WR_REG(0x0053,0x013F); // Vertical GRAM Start Address
LCD_WR_REG(0x0060,0xA700); // Gate Scan Line
LCD_WR_REG(0x0061,0x0001); // NDL,VLE);lcd_data(REV
LCD_WR_REG(0x006A,0x0000); // set scrolling line
//-------------- Partial Display Control ---------//
LCD_WR_REG(0x0080,0x0000);
LCD_WR_REG(0x0081,0x0000);
LCD_WR_REG(0x0082,0x0000);
LCD_WR_REG(0x0083,0x0000);
LCD_WR_REG(0x0084,0x0000);
LCD_WR_REG(0x0085,0x0000);
//-------------- Panel Control -------------------//
LCD_WR_REG(0x0090,0x0010);
LCD_WR_REG(0x0092,0x0600);
LCD_WR_REG(0x0007,0x0133); // 262K color and display ON
 
 LCD_WR_REG16(0x0022);   //  RAM Data Write/Read

}


void LCD_ON()
{
	/*
LCD_WR_REG(0x0100,0x4110);
LCD_WR_REG(0x0111,0x061c);
LCD_WR_REG(0x0110,0x0101);
LCD_WR_REG(0x0007,0x0001);
delay_ms(45);
LCD_WR_REG(0x0111,0x161b);
LCD_WR_REG(0x0110,0x0101);
LCD_WR_REG(0x0007,0x0003);
delay_ms(45);
LCD_WR_REG(0x0007,0x0113);
*/
}


/*


// BLACK;0x0000, WHITE;0xffff,YELLOW;0xffe0,  RED;0xf800, GREEN;0x07e0,
// BLUE;0x001f,  CYAN;0x07ff, MAGENTA; 0xf81f

// =============================== 바탕색 설정 ===============================
// ex => mainscreen(GREEN);
// -----------------------------------------------------------------------------
void mainscreen(unsigned color)
{
	screen_color = color;					// 문자색 설정
}

// =============================== 문자색 설정 ===============================
// ex => textcolor(BLUE);
// -----------------------------------------------------------------------------
void textcolor(unsigned color)
{
	screen_bkcolor = color;				// 문자색 설정
}
*/


void LCD_Clear(void)
{  long int i;  
	
	LCD_WR_REG(0x0020,0x0000);
	LCD_WR_REG(0x0021,0x0000);
	 
  LCD_WR_REG(0x0050,0x0000); // Horizontal GRAM Start Address
  LCD_WR_REG(0x0051,0x00EF); // Horizontal GRAM End Address
  LCD_WR_REG(0x0052,0x0000); // Vertical GRAM Start Address
  LCD_WR_REG(0x0053,0x013F); // Vertical GRAM Start Address

   LCD_WR_REG16(0x0022);   //  RAM Data Write/Read
   for(i=0;i<MAX_DOT;i++)
      LCD_WR_DATA16(WHITE); //test WHITE
}

void LCD_gotoxy(unsigned int data1, unsigned int data2)
{  LCD_WR_REG16(0x0020);
   LCD_WR_DATA16(data2);   // Horizontal Address
   LCD_WR_REG16(0x0021);
   LCD_WR_DATA16(data1);   // Vertical Address
}

void LCD_Dot(unsigned int data)
{  LCD_WR_REG16(0x0022);   //  RAM Data Write/Read
   LCD_WR_DATA16(data);    // data = Dot color
}


void G_d(unsigned int p,unsigned int p1)// p1 color
{
     LCD_RD_H;
	   LCD_RS_L;
     LCD_CS_L;  
     LCD_WR_L;
     PORTF=p>>8; 
     LCD_WR_H;
     LCD_WR_L;
     PORTF=p1&0XFF; 
     LCD_WR_H;
     LCD_CS_H;

 //PORTB = 0x28;
 ///PORTB = 0x38;
}


// ============================= 그래픽 좌표 지정 ==============================
// [인수] int x,int y
// Item1: 시작점의 x좌표 : 가로면 표시시(0-319) / 세로면 표시시(0-239)
// Item2: 시작점의 y좌표 : 가로면 표시시(0-239) / 세로면 표시시(0-319)
// [설명] 가로 화면시(0,0,319,239)
//        세로 화면시(0,0,239,319)
// -----------------------------------------------------------------------------
void Gotoxy(int x,int y)
{
	if(x >= 0 && x <= screen_xmax){			// X범위 초과 검사
		if(y >= 0 && y <= screen_ymax){		// Y범위 초과 검사
	                 screen_curx = x;
			screen_cury = y;
		}
	}
}

// ======================= 화면에 텍스트 좌표를 지정 ===========================
// Item1: 시작점의 x좌표 : 가로면 표시시(1-20) / 세로면 표시시(1-10)
// Item2: 시작점의 y좌표 : 가로면 표시시(1-10) / 세로면 표시시(1-20)
// [설명] 가로 화면시(1,1,40,15)
//        세로 화면시(1,1,15,40)
// [참조] _screen_curx,_screen_cury
// -----------------------------------------------------------------------------
void Gotoxyt(int x,int y)
{
	int x1 = (x-1) * 16,y1;
	y1 = (y-1) * 24;
	if(x1 >= 0 && x1 <= screen_xmax){
		if(y1 >= 0 && y1 <= screen_ymax){
			screen_curx = x1;
			screen_cury = y1;
		}
	}
}



/*
// ======================= 영문 폰트 데이테 로드 ===============================
//  [인수] char c
//  Item1: 변환할 데이타
//  리턴 : 변환된 버퍼 포인터
// -----------------------------------------------------------------------------
void *GetAscImage(int c)
{
	return AscFont16[c];
}


// ========================= 바이트 단위 문자 출력 지원 =========================
// [인수] unsigned int	c
// Item1: 출력할 문자
// ------------------------------------------------------------------------------
void Putcht(unsigned int c)
{
int i;
unsigned char *image;
		image = GetAscImage(c);		// 영문 자형을 구함
						
		if(c == 0x0a){	// 영문 코드 데이타
			// 전체 화면 좌표 설정	
			if(screen_mode == SCREEN_COLUMN_SET){
				screen_xmax = SCREEN_COLUMN_X;// 가로면 최대값
				screen_ymax = SCREEN_COLUMN_Y;// 세로면 최대값
			}
			else{
				screen_xmax = SCREEN_ROW_X;	// 가로면 최대값
				screen_ymax = SCREEN_ROW_Y;	// 세로면 최대값
			}
			// Y커저 증가
			screen_cury += 16;			// 커서 세로 포인터 증가
			if(screen_cury > screen_ymax) screen_cury = 0;// 커서 세로 포인터 검색
		}
		else if(c == 0x0d) screen_curx = 0;		// Carrage Return
		else{
			image = GetAscImage(c);		// 영문 자형을 구함
		
		}


}



// ============================== 한문자를 출력 한다. ==========================
// [인수] unsigned c
// Item1: 출력할 문자(한글 코드 제외)
// -----------------------------------------------------------------------------
void Putch(unsigned c)
{
	Putcht(c&0xff);						// 1바이트 문자를 표시
}


// ================ 지정한 그래픽 좌표에 한문자를 출력 한다. ===================
// [인수] int x
//	  int y
//	  unsigned c
// Item1: 출력할 문자 가로 위치(0 - 319)
// Item2: 출력할 문자 세로 위치(0 - 239)
// Item3: 출력할 문자(한글 코드 제외)
// -----------------------------------------------------------------------------
void Putchxy(int x,int y,unsigned c)
{
	Gotoxy(x,y);						// Base Cursor Point Set
	Putcht(c);						// 1바이트 문자를 표시
}



// =================== 지정한 텍스트 좌표에 한문자를 출력 한다. ================
// Item1: 시작점의 x좌표 : 가로면 표시시(1-20) / 세로면 표시시(1-10)
// Item2: 시작점의 y좌표 : 가로면 표시시(1-10) / 세로면 표시시(1-20)
// Item3: 출력할 문자(한글 코드 제외)
// -----------------------------------------------------------------------------
void Putchxyt(int x,int y,unsigned c)
{
	Gotoxyt(x,y);						// Base Cursor Point Set
	Putch(c);						// 1바이트 문자를 표시
}

*/


/*
 
// ==================== 현재 커저 위치에  문자열을 출력 한다. ==================
// [인수] const char *str
// Item1: 출력할 문자열(한영)
// -----------------------------------------------------------------------------
void Puts(const char *str)
{
unsigned char byte1st = 0,c;
unsigned datau,i = 0;

	Han_Conv((char*)str);					// 완성형을 조합형으로 변환
	while((c = han_conv_buf[i++]) != 0){			// 소스에서 Han_Conv() 사용시
//	while((c = *str++) != 0){				// 윈도우에서 완성형->조합형 생성기 사용시
		if(byte1st){
			datau = ((unsigned)byte1st << 8) | (unsigned)c;
			_Putch(datau);				// 한글 문자를 표시
			byte1st = 0;                    	
		}                                       	
		else if(c & 0x80){                      	
			byte1st = c;				// 한글 데이타 저장
		}                                       	
		else{                                   	
			if(c == 0x0a){				// 라인 피드
				_Putch(0x0d);           	
				_Putch(0x0a);           	
			}                               	
			else _Putch(c); 			// 영문 문자를 표시
		}
	}
}

*/





// =============================== 화면에 점을 찍음 ============================
// [인수] int x,int y,unsigned color
// Item1: 시작점의 x좌표(0-319)
// Item2: 시작점의 y좌표(0-219)
// Item3: 표시할 색상(_RED,_GREEN,BLUE,_WHITE,_BLACK...)
// [설명] 가로 화면시(0,0,319,239)
//        세로 화면시(0,0,239,319)
// -----------------------------------------------------------------------------
void Putpixel(int x,int y,unsigned color)
{
//	ScreenSet(screen_mode,x,y,x,y);			// 표시 화면 지정


   LCD_WR_REG16(0x0020);
   LCD_WR_DATA16(y);   // Horizontal Address
   LCD_WR_REG16(0x0021);
   LCD_WR_DATA16(x);   // Vertical Address

  LCD_WR_REG16(0x0022);   //  RAM Data Write/Read
   LCD_WR_DATA16(color);    // data = Dot color
}


void tftlcdSetPixel (unsigned int x,unsigned int y, unsigned int color)
{
	 if(x>(X_MAX_PIXEL -1))
	  x = (X_MAX_PIXEL -1);

	 if(y>(Y_MAX_PIXEL-1))
	  y = (Y_MAX_PIXEL -1);
	Putpixel(x,y,color);  //pixel =>  Putpixel
	
	
	/*
	 Init_Data(0x0002,startx >> 8);
	 Init_Data(0x0003,startx);
	 Init_Data(0x0004,startx >> 8);
	 Init_Data(0x0005,startx);
	 Init_Data(0x0006,starty >> 8);
	 Init_Data(0x0007,starty);
	 Init_Data(0x0008,starty >> 8);
	 Init_Data(0x0009,starty);
	 WriteI(0x0022);
 
	 sbi(RS_PORT, RS);
	 cbi(NCS_PORT, NCS);
	 outb(LCDLOW_DATAPORT_PORT, (u08)(color & 0x00FF));    	 
   	 outb(LCDHI_DATAPORT_PORT, (u08)(color >> 8));

     cbi(NWR_PORT, NWR);
	 sbi(NWR_PORT, NWR);
	
	 sbi(NCS_PORT, NCS);
*/
}

void tftlcdWriteChar(unsigned int x, unsigned int y, unsigned char c, unsigned int color)
{
	unsigned char i = 0, j = 0;
	unsigned char data;
	for(i=0; i<16; i++)  { //5   16	{
		data = pgm_read_byte(&Font5x7[((c - 0x20) * 16) + i]);  //5  16
		for(j = 0; j < 8; j++)   //8,10
		{
			if (data & (1 << j))
				tftlcdSetPixel(x + i, y + j, color);
			//else	tftlcdSetPixel(x + i, y + j, 0xffff);  //추가 하면 흰박스안에 글씨 
		}
	}
}

void tftlcdPutStr(unsigned int x, unsigned int y, unsigned char *data, unsigned int color)
{
	while (*data) {
    	tftlcdWriteChar(x, y, *data, color);
    	data++;
    	x += 8;
    	if (x >= X_MAX_PIXEL)
    	{
    		x = 0;
    		y += 8;      //8,10
    	}
  	}
}


//#define X_MAX_PIXEL  400 #define Y_MAX_PIXEL  240

/*

void tftlcdImageWrite (unsigned int startx,unsigned int starty,unsigned int imageWidth,unsigned int imageHeight, const unsigned int *image)
{
	 unsigned int i,j;
	 unsigned int data, cnt = 0; 	
	 unsigned int endx, endy;

	endx = startx + imageWidth - 1;
	endy = starty + imageHeight - 1;
	
	//Putpixel(startx,starty,color);  //pixel =>  Putpixel
LCD_WR_REG16(0x0200);
   lcd_data(starty);   // Horizontal Address
   LCD_WR_REG16(0x0201);
   lcd_data(startx);   // Vertical Address
LCD_WR_REG16(0x0202);   //  RAM Data Write/Read

	 for(i = 0;i < imageHeight; i++)
	 {
	     for(j= 0; j< imageWidth; j++)
	     {  
	     	data = pgm_read_word(&image[cnt]);	
		// lcd_data(color);    // data = Dot color
		//outb(LCDLOW_DATAPORT_PORT, (u08)(data & 0x00FF)); 	 
		//outb(LCDHI_DATAPORT_PORT, (u08)(data >> 8));
		  //cbi(NWR_PORT, NWR);
		  //sbi(NWR_PORT, NWR);
LCD_WR_REG16(0x0200);
   lcd_data(starty);   // Horizontal Address
   LCD_WR_REG16(0x0201);
   lcd_data(startx);   // Vertical Address
		
 LCD_WR_REG16(0x0202);   //  RAM Data Write/Read
   lcd_data(cnt);    // data = Dot color
	    cnt++;
	     }
	} 
     
 //	  sbi(NCS_PORT, NCS);

}

*/





void TFT_screen_mode(U08 mode)			// set screen direction mode
{
  if((mode == 'P') || (mode == 'p'))		// portrait mode(30x40 character unit)
    { ScreenMode = 'P';
      LineLimit = 30;
    }
  else						// landscape mode(40x30 character unit)
    { ScreenMode = 'L';
      LineLimit = 40;
    }
}




void TFT_English(U08 code)			/* write a English ASCII character */
{
  unsigned char data, x, y;
  unsigned int pixel[8][16];
  unsigned int dot0, dot1, dot2, dot3, dot4;

  for(x = 0; x < 8; x++)			// read English ASCII font
    { data = pgm_read_byte(&E_font[code][x]);
      for(y = 0; y < 8; y++)
        { if(data & 0x01) pixel[x][y] = foreground;
	  else            pixel[x][y] = background;
	  data = data >> 1;
	}
    }

  for(x = 0; x < 8; x++)
    { data = pgm_read_byte(&E_font[code][x+8]);
      for(y = 0; y < 8; y++)
	{ if(data & 0x01) pixel[x][y+8] = foreground;
	  else            pixel[x][y+8] = background;
	  data = data >> 1;
	}
    }

  if(outline_flag == 1)				// display outline
    for(x = 0; x < 8; x++)
      { dot0 = pgm_read_byte(&E_font[code][x]) + pgm_read_byte(&E_font[code][x+8])*256;
        dot1 = dot0 >> 1;								 // up side
        dot2 = dot0;									 // down side
        dot3 = pgm_read_byte(&E_font[code][x+1]) + pgm_read_byte(&E_font[code][x+9])*256;// left side
        dot4 = pgm_read_byte(&E_font[code][x-1]) + pgm_read_byte(&E_font[code][x+7])*256;// right side

        for(y = 0; y < 15; y++)
	  { if(!(dot0 & 0x0001))
	      { if(dot1 & 0x0001) pixel[x][y] = outline;
	        if(dot2 & 0x0001) pixel[x][y] = outline;
	        if((dot3 & 0x0001) && (x < 7 )) pixel[x][y] = outline;
	        if((dot4 & 0x0001) && (x > 0 )) pixel[x][y] = outline;
	      }

            dot1 >>= 1;
            dot2 = dot0;
	    dot0 >>= 1;
	    dot3 >>= 1;
	    dot4 >>= 1;
          }
      }

  if((cursor_flag == 1) && (xcharacter == xcursor) &&(ycharacter == ycursor))
    { for(x = 0; x < 8; x++)			// display cursor
        { pixel[x][14] = cursor;
          pixel[x][15] = cursor;
        }
    }

  if(ScreenMode == 'P')
    { for(y = 0; y < 16; y++)			// write in portrait mode
        for(x = 0; x < 8; x++)
          tftlcdSetPixel(xcharacter*8 + x, ycharacter*8 + y, pixel[x][y]);
    }
  else
    { for(y = 0; y < 16; y++)			// write in landscape mode
        for(x = 0; x < 8; x++)
        tftlcdSetPixel((29-ycharacter)*8 + 7 - y, xcharacter*8 + x, pixel[x][y]);
    }

  xcharacter += 1;
  if(xcharacter >= LineLimit)			// end of line ?
    { xcharacter = 0;
      ycharacter += 2;
    }
}




unsigned int KS_code_conversion(U16 KSSM)	/* convert KSSM(완성형) to KS(조합형) */
{
  unsigned char HB, LB;
  unsigned int index, KS;

  HB = KSSM >> 8;
  LB = KSSM & 0x00FF;

  if(KSSM >= 0xB0A1 && KSSM <= 0xC8FE)
    { index = (HB - 0xB0)*94 + LB - 0xA1;
      KS  =  pgm_read_byte(&KS_Table[index][0]) * 256;
      KS |=  pgm_read_byte(&KS_Table[index][1]);

      return KS;
    }
  else
    return -1;
}



void TFT_string(U08 xChar, U08 yChar, U16 colorfore, U16 colorback, char *str)	/* write TFT-LCD string */
{
  unsigned char ch1;
  unsigned int ch2;

  xcharacter = xChar;
  ycharacter = yChar;

  foreground = colorfore;
  background = colorback;

  while(*str)
    { ch1 = *str;
      str++;

      if(ch1 < 0x80)				// English ASCII character
	TFT_English(ch1);
      else					// Korean
	{ ch2 = (ch1 << 8) + (*str);
          str++;
	  ch2 = KS_code_conversion(ch2);	// convert KSSM(완성형) to KS(조합형)
	  TFT_Korean(ch2);
	}
   }
}



void TFT_Korean(U16 code)			/* write a Korean character */
{
  unsigned char cho_5bit, joong_5bit, jong_5bit;
  unsigned char cho_bul, joong_bul, jong_bul = 0, i, jong_flag;
  unsigned int ch;

  cho_5bit   = pgm_read_byte(&table_cho[(code >> 10) & 0x001F]);  // get 5bit(14-10) of chosung
  joong_5bit = pgm_read_byte(&table_joong[(code >> 5) & 0x001F]); // get 5bit(09-05) of joongsung
  jong_5bit  = pgm_read_byte(&table_jong[code & 0x001F]);	  // get 5bit(04-00) of jongsung

  if(jong_5bit == 0)				// if jongsung not exist
    { jong_flag = 0;
      cho_bul = pgm_read_byte(&bul_cho1[joong_5bit]);
      if((cho_5bit == 1) || (cho_5bit == 16))
   	joong_bul = 0;
      else
	joong_bul = 1;
    }
  else						// if jongsung exist
    { jong_flag = 1;
      cho_bul = pgm_read_byte(&bul_cho2[joong_5bit]);
      if((cho_5bit == 1) || (cho_5bit == 16))
	joong_bul = 2;
      else
	joong_bul = 3;
      jong_bul = pgm_read_byte(&bul_jong[joong_5bit]);
    }

  ch = cho_bul*20 + cho_5bit;			// get chosung font 
  for(i = 0; i < 32; i++)
    KoreanBuffer[i] = pgm_read_byte(&K_font[ch][i]);
  ch = 8*20 + joong_bul*22 + joong_5bit;	// OR joongsung font
  for(i = 0; i < 32; i++)
    KoreanBuffer[i] |= pgm_read_byte(&K_font[ch][i]);
  if(jong_flag)					// OR jongsung font
    { ch = 8*20 + 4*22 + jong_bul*28 + jong_5bit;
      for(i = 0; i < 32; i++)
	KoreanBuffer[i] |= pgm_read_byte(&K_font[ch][i]);
    }

  unsigned char data, x, y;
  unsigned int pixel[16][16];
  unsigned int dot0, dot1, dot2, dot3, dot4;

  for(x = 0; x < 16; x++)			// read Korean font
    { data = KoreanBuffer[x];
      for(y = 0; y < 8; y++)
	{ if(data & 0x01) pixel[x][y] = foreground;
	  else            pixel[x][y] = background;
	  data = data >> 1;
	}
    }

  for(x = 0; x < 16; x++)
    { data = KoreanBuffer[x+16];
      for(y = 0; y < 8; y++)
	{ if(data & 0x01) pixel[x][y+8] = foreground;
	  else            pixel[x][y+8] = background;
	  data = data >> 1;
	}
    }

  if(outline_flag == 1)				// display outline
    for(x = 0; x < 16; x++)
      { dot0 = KoreanBuffer[x] + KoreanBuffer[x+16]*256;
        dot1 = dot0 >> 1;				   // up side
        dot2 = dot0;					   // down side
        dot3 = KoreanBuffer[x+1] + KoreanBuffer[x+17]*256; // left side
        dot4 = KoreanBuffer[x-1] + KoreanBuffer[x+15]*256; // right side

        for(y = 0; y < 16; y++)
	  { if(!(dot0 & 0x0001))
	      { if(dot1 & 0x0001) pixel[x][y] = outline;
	        if(dot2 & 0x0001) pixel[x][y] = outline;
 	        if((dot3 & 0x0001) && (x < 15 )) pixel[x][y] = outline;
	        if((dot4 & 0x0001) && (x > 0 ))  pixel[x][y] = outline;
	      }

	    dot1 >>= 1;
	    dot2 = dot0;
	    dot0 >>= 1;
	    dot3 >>= 1;
	    dot4 >>= 1;
          }
      }

  if((cursor_flag == 1) && (xcharacter == xcursor) &&(ycharacter == ycursor))
    { for(x = 0; x < 16; x++)			// display cursor
        { pixel[x][14] = cursor;
          pixel[x][15] = cursor;
        }
    }

  if(xcharacter >= (LineLimit-1))		// end of line ?
    { xcharacter = 0;
      ycharacter += 2;
    }

  if(ScreenMode == 'P')				// write in portrait mode
    { for(y = 0; y < 16; y++)
        for(x = 0; x < 16; x++)
          tftlcdSetPixel(xcharacter*8 + x, ycharacter*8 + y, pixel[x][y]);
    }
  else						// write in landscape mode
    { for(y = 0; y < 16; y++)
        for(x = 0; x < 16; x++)
         tftlcdSetPixel((29-ycharacter)*8 + 7 - y, xcharacter*8 + x, pixel[x][y]);
    }

  xcharacter += 2;
  if(xcharacter >= LineLimit)			// end of line ?
    { xcharacter = 0;
      ycharacter += 2;
    }
}

void TFT_cursor(U16 cursor_color)		/* set cursor and color */
{
  if(cursor_color == Transparent)		// disable cursor
    cursor_flag = 0;
  else						// enable cursor
    { cursor_flag = 1;
      cursor = cursor_color;
    }
}


/*

void TFT_outline(U16 outline_color)		// set outline and color 
{
  if(outline_color == Transparent)		// disable outline
    outline_flag = 0;
  else						// enable outline
    { outline_flag = 1;
      outline = outline_color;
    }
}

*/


void ScreenSet(int mode,int x1,int y1,int x2,int y2)
{

	if(mode == SCREEN_COLUMN_SET){
	LCD_WR_REG16(0x0020);
	//	CLCD_Command_Data(0x16,0x00a8);			// Memory Access Contro : MV=1, MX=0, MY=1, BGR=1 mode.
		screen_mode = SCREEN_COLUMN_SET;		// 화면 가로 배치Horizontal
		screen_xmax = x2;				// 가로면 최대값
		screen_ymax = y2;				// 세로면 최대값
	}
	else{
LCD_WR_REG16(0x0021);   //  RAM Data Write/Read
	//	CLCD_Command_Data(0x16,0x00c8);			// Memory Access Contro : MV=1, MX=1, MY=1, BGR=1 mode.
		screen_mode = SCREEN_ROW_SET;			// 화면 세로 배치Vertical
		screen_xmax = x2;				// 가로면 최대값
		screen_ymax = y2;				// 세로면 최대값
	}


// Memory access
LCD_WR_REG(0x0050,0x0000); // Horizontal GRAM Start Address
LCD_WR_REG(0x0051,0x00EF); // Horizontal GRAM End Address
LCD_WR_REG(0x0052,0x0000); // Vertical GRAM Start Address
LCD_WR_REG(0x0053,0x013F); // Vertical GRAM Start Address



/*
	CLCD_Command_Data(0x02,(x1>>8)&0xff);			// Column Address Start Register SC[8..15]
	CLCD_Command_Data(0x03,x1&0xff);			// Column Address Start Register SC[0..7]

	CLCD_Command_Data(0x06,(y1>>8)&0xff);			// Row Address Start Register SP[8..15]
	CLCD_Command_Data(0x07,y1&0xff);			// Row Address Start Register SP[0..7]

	CLCD_Command_Data(0x04,(x2>>8)&0xff);			// Column Address End Register EC[8..15]
	CLCD_Command_Data(0x05,x2&0xff);			// Column Address End Register EC[0..7]

	CLCD_Command_Data(0x08,(y2>>8)&0xff);			// Row Address End Register EP[8..15]
	CLCD_Command_Data(0x09,y2&0xff);			// Row Address End Register EP[0..7]

*/

}





// ============== TFT LCD에 정해진 위치에 색으로 직선              ___________
// ex1 => Line(x좌표시작점,y좌표 시작점, x좌표 끝점, y좌표 끝점   |           |
// ex2 => Line(50,120,100,200,RED);                               |           |
// -------------------------------------------------------         -----------
void Line(int x1,int y1,int x2,int y2, unsigned color)
{
int i,vdx,vdy,vix,viy,vinc,plot,plotx,ploty,x = 0,y = 0;

	vdx = x2 - x1;						// vdx = x2 - x1
	vdy = y2 - y1;						// vdy = y2 - y1
	vix = abs(vdx);						// vix = |vdx|
	viy = abs(vdy); 					// vix = |vdx|
	if(vix > viy) vinc = vix;				// vinc = vix ? viy;
	else vinc = viy;

	plotx = x1;
	ploty = y1;
	Putpixel(plotx,ploty,color);  //pixel =>  Putpixel
	for(i = 0; i <= vinc; i++){
		x += vix;
		y += viy;
		plot = 0;
		if(x > vinc){
			x -= vinc;
			if(vdx > 0) plotx++;
			if(vdx < 0) plotx--;
			plot = 1;
		}
		if(y > vinc){
			y -= vinc;
			if(vdy > 0) ploty++;
			if(vdy < 0) ploty--;
			plot = 1;
		}
		if(plot)Putpixel(plotx,ploty,color);
	}
	//if(screen_mode == SCREEN_COLUMN_SET) ScreenSet(SCREEN_COLUMN_SET,0,0,SCREEN_COLUMN_X,SCREEN_COLUMN_Y);// 표시화면 가로 지정
	//else
    //                                     ScreenSet(SCREEN_ROW_SET,0,0,SCREEN_ROW_X,SCREEN_ROW_Y);// 표시화면 세로 지정
}







 void Rectangle(int x1,int y1,int x2,int y2, unsigned color)
{
	Line( x1, y1, x2, y1, color);
	Line( x2, y1, x2, y2, color);
	Line( x1, y2, x2, y2, color);
	Line( x1, y1, x1, y2, color);


}



void red_set(void)
{
unsigned long dd;

for(dd=0;dd<76800 ;dd++){
G_d(0x03,0xffff); //0x03 => color 3만큼 쉬프트 
}
delay_ms(100);	delay_ms(500);
for(dd=0;dd<76800 ;dd++){
G_d(0x00,0x0000);  //0
}
delay_ms(100);	delay_ms(500);
for(dd=0;dd<76800 ;dd++){
G_d(0x00,0x003f); //0
}
delay_ms(100);	delay_ms(500);
for(dd=0;dd<76800 ;dd++){
G_d(0x00,0x0fc0); //0
}

delay_ms(100);	delay_ms(500);
for(dd=0;dd<76800 ;dd++){
G_d(0x03,0xf000);
}

delay_ms(100);
for(dd=0;dd<76800 ;dd++){
G_d(0x1,0x2222);
}
delay_ms(100);
for(dd=0;dd<76800 ;dd++){
G_d(0x01,0x6666);
}
delay_ms(100);
for(dd=0;dd<76800 ;dd++){
G_d(0x00,0xacac);
}
delay_ms(100);
for(dd=0;dd<76800 ;dd++){
G_d(0x00,0x1111);
}
delay_ms(100);
}
// ============ 16bit 이미지 데이터 표시(화면 전체 또는 큰 화면) ===============
// [인수] int mode,int x,int y,int x_size,int y_size,unsigned char *image1,unsigned char *image2,unsigned char *image3
// Item1: 화면 모드 설정 :: _SCREEN_COLUMN_SET(가로 화면), _SCREEN_ROW_SET(세로 화면)
// Item2: 시작점의 x좌표 : 가로면 표시시(0-319) / 세로면 표시시(0-239)
// Item3: 시작점의 y좌표 : 가로면 표시시(0-239) / 세로면 표시시(0-319)
// Item4: x축 이미지 크기
// Item5: y축 이미지 크기
// Item6: 표시할 이미지 데이터1(32000Byte 이내)
// Item7: 표시할 이미지 데이터2(32000Byte 이내)
// Item8: 표시할 이미지 데이터3(32000Byte 이내)
// Item9: 표시할 이미지 데이터4(32000Byte 이내)
// Item10:표시할 이미지 데이터5(32000Byte 이내)
// [설명] 가로 화면시(0,0,319,239)
//        RGB(565) : RRRRRGGGGGGBBBBB
// -----------------------------------------------------------------------------
void Image_Screen_Disp_16bit(int mode,int x, int y, int x_size,int y_size,unsigned char *image1,unsigned char *image2,unsigned char *image3,unsigned char *image4,unsigned char *image5)
{
unsigned char *image;
unsigned i,j,total_cnt = 0,total_size;
long total_sizel;

	ScreenSet(mode,x,y,x+(x_size-1),y+(y_size-1));		// 표시화면(가로/세로) 지정
	total_sizel = (long)x_size * (long)y_size;		// 전체 표시 갯수 구함
	if(total_sizel >= 32000L){
		total_cnt = (unsigned)(total_sizel / 32000L);	// LOOP 카운터 갯수
		i = (unsigned)(total_sizel % 32000L);		// 나머지?
		if(i != 0) total_cnt++;
		total_size = 32000U;				// 버퍼 갯수			
	}
	else if(total_sizel > 0){				// 나머지가 0보다 크면
		total_size = (unsigned)total_sizel; 
		total_cnt = 1;
	}
	//CLCD_Command(0x22);					// Set LCD register address 0x22 for make the system take GRAM data.
	//PORTE |= 0x20;						// PORTE.5 :: CLCD RS = 1 :: Data Set
	//PORTG &= ~0x04;						// PORTG.2 :: CLCD_CS = 0
	//PORTG |= 0x01;						// PORTG.0 :: CLCD_WR\ = 1
	LCD_WR_REG16(0x0022);   //  RAM Data Write/Read
	LCD_RS_H;
	LCD_CS_L;
    LCD_WR_H;

		
	for(i = 0; i < total_cnt; i++){				// 전체 버퍼 갯수?
		if(i > 0){					// 첫번째 버퍼 제외
			if(total_sizel >= 32000L){		// 표시할 갯수 계산
				total_size = 32000;
				total_sizel -= 32000L;
			}
			else total_size = (unsigned)total_sizel; 
		}
	
	switch(i){
			case 0: image = image1;			// 이미지 데이터1
				break;
			case 1: image = image2;			// 이미지 데이터2
				break;
			case 2: image = image3;			// 이미지 데이터3
				break;
			case 3: image = image4;			// 이미지 데이터4
				break;
			case 4: image = image5;			// 이미지 데이터5
				break;
			default: break;
		}

	
		for(j = 0; j < total_size; j++){		// 전체 갯수(64000Byte 이내)
			PORTC = pgm_read_byte(image++);		// Data Read D[8..15]
			PORTF = pgm_read_byte(image++);		// Data Read D[0..7]
	
		//	PORTG &= ~0x01;				// PORTG.0 :: CLCD_WR\ = 0
		//	PORTG |= 0x01;				// PORTG.0 :: CLCD_WR\ = 1
	LCD_WR_L;
	LCD_WR_H;
		}
	}
//	PORTG |= 0x04;						// PORTG.2 :: CLCD_CS = 1
	LCD_CS_H;

}



void draw_bird0(void)
{
	unsigned char i = 0, j = 0;
	unsigned char data;
//CLCD_Command(0x22);	

for(i=0;i<2960;i++) //5   14
	{
		data = pgm_read_byte(i);  //5  14
		for(j = 0; j < 320; j++)   //8,10
		{
			if (data & (1 << j))
		
	
	data = pgm_read_byte(j++);	
		
		
			//	tftlcdSetPixel(x + i, y + j, color);
			//else	tftlcdSetPixel(x + i, y + j, 0xffff);  //추가 하면 흰박스안에 글씨 
		}
	}
}

void Demo_display_8_color(void)
{
   unsigned int row, idx, cnt;

   LCD_WR_REG16(0x0022);  //0020
      
   // Display Direction (Top->Down)

   for(row=0;row<X_MAX_PIXEL;row++)
      for(idx=0;idx<8;idx++)
         for(cnt=0;cnt<Y_MAX_PIXEL/8;cnt++)
            LCD_WR_DATA16(basic_color[idx]);
}


void Demo_display_16_gray(void)
{
   unsigned int row, idx, cnt;

   LCD_WR_REG16(0x0022);  //0020
      
   // Display Direction (Top->Down)

   for(row=0;row<X_MAX_PIXEL;row++)
      for(idx=0;idx<16;idx++)
         for(cnt=0;cnt<Y_MAX_PIXEL/16;cnt++)
            LCD_WR_DATA16(gray16[idx]);
}













