/*--------------------------------------------------------------------------/
/  XD1602A0 Test Code - R0.004b                (C)NSYSTECH, 2007
/---------------------------------------------------------------------------/
/  XD1602A0
/
/  (Dot-Matrix Liquid Crystal Display One-Chip Controller/
             Driver Supporting Korean/Japanese/Russian/Latin Font Display)
/
/ NSYSTECH
/---------------------------------------------------------------------------/
/
/ Description
/ The XD1602A0 is a dot-matrix liquid crystal display controller (LCD) and 
driver LSI that displays Korean characters consisting of hiragana and 
katakana according to the Korean Industrial Standard KSC 5601. 
The XD1602A0 incorporates the following five functions on a single chip: 
(i) display control function for the dot matrix LCD, 
(ii) a display RAM to store character codes, 
(iii) ROM fonts to support Korean, 
(iv) liquid crystal driver, and 
(v) a booster to drive the LCD. 
A two 16-character (XD1602A0) Korean display can easily be achieved 
by receiving character codes (2 bytes/character) from the MPU.

/ The font ROM includes 2,350 Korean characters from the KSC5601 Set, 
  and 128 half-size alphanumeric characters and symbols. 
  Full-size fonts such as Korean/Japanese/English/Russian/Latin and 
  half-size of fonts
  such as alphanumeric characters can be displayed together.
  
/ In addition, display control equivalent to full bit mapping can be 
  performed through horizontal and vertical
  dot-by-dot smooth scroll functions for each display line. 
	
/  Copyright (C) 2007, NSYSTECH.CO.,LTD All Right Reserved.
/---------------------------------------------------------------------------/
/  Feb 26, 2007  R0.00  Prototype.
/---------------------------------------------------------------------------*/

// 89C4051
#include <AT89X051.h>           // I/O°¡ Á¤ÀÇ µÇ¾î ÀÖ´Â Çì´õ ÆÄÀÏ

typedef char            BYTE;
typedef unsigned char   UBYTE;
typedef unsigned short  ULONG;

#define  RS_LCD		P3_2		//RS     P3_0
#define  WR_LCD		P3_1		//WR     P3_1
#define  EN_LCD		P3_0		//Enable

#define P3DR 		P1  		//DATA


#define SW1			P3_4
#define SW2			P3_5

/* XD1602 LCD */
#define     LCD_EMR		0	// Entry mode
#define     LCD_FSR 	1	// Function Set
#define     LCD_CCR 	2	// Cursor control
#define     LCD_DCR1    3	// Display Control 1
#define     LCD_DCR2    4	// Display Control 2
#define     LCD_SCR1    5	// Scroll Control 1
#define     LCD_SCR2    6	// Scroll Control 2
#define     LCD_SCR3    7	// Scroll Control 3
#define     LCD_RAR 	8	// RAM Address 1
#define     LCD_RDR     9	// RAM Data 1
#define     LCD_TSR 	0xF	// Test 1


/* LCD_TYPE */
//#define     ASCII_ONLY      0
#define     KOREAN_PLUS     1


void delay(ULONG i);
void delay_ms(ULONG ms);

void lcd_clear();

void LCD_RCR();  
void LCD_EN();
void LCD_DEN();
void LCD_READY_CHK();
void LCD_CONT_REG_WRITE(UBYTE reg_no, UBYTE control_data);
void LCD_INIT() ;
void CGRAM_INIT();

void lcd_print(ULONG font_addr);
void CGRAM_ADDR(UBYTE cgram_addr);
void lcd_xy(UBYTE x, UBYTE y); 

void half_print(UBYTE font_addr);
void half_xy(UBYTE x, UBYTE y);

UBYTE	lcd_type;
UBYTE	font_type;
UBYTE posx, posy;

UBYTE CGRAM_DATA2[26]= { 
	// ¡à
	0x3f, 0x3f, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20,
		0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x3f, 0x3f, 0x00, 0x00
} ;

UBYTE CGRAM_DATA3[26]= { 
	// ¡à
	0x3f, 0x3f, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20,
		0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x3f, 0x3f, 0x00, 0x00
} ;


unsigned int n_dsp=4;

void LCD_RCR()
{
	WR_LCD=1;          /* LCD read mode set */
	RS_LCD=0;          /* get control register */
}

void LCD_EN()
{
	EN_LCD=1;           /* LCD enable */
}

void LCD_DEN()
{
	EN_LCD=0;           /* LCD disable */
}

void delay_ms(ULONG ms)
{ 
	ULONG i, j;
	
	for(i = 1; i <= ms; i++)
		for(j = 1; j <= 125; j++);
		
}

// delay
void DELAY(ULONG i)
{
	while(i--);
}

void LCD_READY_CHK()
{
	UBYTE   temp1;
	
	temp1=0;
	
	LCD_RCR();              // LCD read mode set 

	do
	{
		LCD_EN();           // LCD enable 
		temp1=P3DR;	
		LCD_DEN();          // LCD enable 
	}while(temp1 &0x80); 	// busy 1ÀÎ°æ¿ì ·çÇÁ
	// busy 0ÀÎ°æ¿ì ¸®ÅÏ.
}



void LCD_CONT_REG_WRITE(UBYTE reg_no, UBYTE control_data)
{ 
	LCD_READY_CHK();
	P3DR=reg_no;
	
	WR_LCD=0;  
	RS_LCD=0; // IDR SELECT : control 	
	LCD_EN();
	LCD_DEN();	           	   
	
	//DELAY(100);  
	LCD_READY_CHK();
	P3DR=control_data;
	WR_LCD=0;  
	RS_LCD=1;				// REGISTER SELECT : data 
	LCD_EN();
	LCD_DEN();	           
	
	//DELAY(100);
	LCD_READY_CHK();
	P3DR=LCD_RDR;			// register nuber 9 , RAM data(RDR)
	WR_LCD=0;  
	RS_LCD=0;				// IDR SELECT : control 
	LCD_EN();
	LCD_DEN();	           	
}


void LCD_INIT() 
{
	// LCD initial
	lcd_type = KOREAN_PLUS;
	font_type=0;

	/* initial configuration */
	LCD_CONT_REG_WRITE(LCD_DCR1,0x02);
	LCD_CONT_REG_WRITE(LCD_DCR2,0x21); 
	LCD_CONT_REG_WRITE(LCD_SCR1,0x00); 
	LCD_CONT_REG_WRITE(LCD_SCR2,0x00); 
	LCD_CONT_REG_WRITE(LCD_SCR3,0x00);
	LCD_CONT_REG_WRITE(LCD_TSR,0x00);

	/* cusor off */
	LCD_CONT_REG_WRITE(LCD_CCR,0x00); 

	/* LCD clear and home */
	LCD_CONT_REG_WRITE(LCD_FSR,0x55); // booster on (bit6:0 changed) 

	/* increment set */
	LCD_CONT_REG_WRITE(LCD_EMR,0x04); 
	
	posx=0;
	posy=0;
}

void lcd_clear()
{ 
	
	LCD_CONT_REG_WRITE(LCD_FSR,0x15); 
	posx=0;	
	posy=0;
	//lcd_xy(posx, posy);
}

void black()
{   
	int i=0;//, x=0;
	
	
	lcd_xy(0,0);
	for(i=0 ; i<16 ; i++){
		lcd_print(0x22a);
		posx=posx+0x02;
	}
	lcd_xy(0,1);
	for(i=16 ; i<32 ; i++){
		lcd_print(0x22a);
		posx=posx+0x02;
	}
}


//----------------------------------------------------------------------
//                          Lcd_Xy
//----------------------------------------------------------------------
void lcd_xy(UBYTE x, UBYTE y)
{
	UBYTE LcdPutXy;
	posx=x;
	posy=y;
	
	//printf("position [x=%02x, y=%02x] \r\n", posx, posy);

	switch(y)
	{
	case 0:                              // first line
		LcdPutXy =  x;
		LCD_CONT_REG_WRITE(LCD_RAR, LcdPutXy);
		break;
	case 1:                              // second line
		LcdPutXy =  x + 0x40;       
		LCD_CONT_REG_WRITE(LCD_RAR, LcdPutXy);
		break;
	default:
		break;
	}
	
	//printf("position [x=%d, y=%d] \r\n", posx, posy);
}


void half_xy(UBYTE x, UBYTE y)
{
	UBYTE LcdPutXy;
	posx=x;
	posy=y;
	
	switch(y)
	{
	case 0:                              // first line
		LcdPutXy =  x;
		LCD_CONT_REG_WRITE(LCD_RAR, LcdPutXy);
		//Put_Lcd_Char(LcdPutXy);
		break;
	case 1:                              // second line
		LcdPutXy =  x + 0x40;       
		LCD_CONT_REG_WRITE(LCD_RAR, LcdPutXy);
		//Put_Lcd_Char(LcdPutXy);
		break;
		
	default:
		break;
	}
	//printf("pos=%02x, ",LcdPutXy);
	//printf("position [x=%d, y=%d] \r\n", posx, posy);
}


void CGRAM_ADDR(UBYTE cgram_addr)
{           
	LCD_READY_CHK();
	
	P3DR=cgram_addr;
	
	WR_LCD=0;  
	RS_LCD=1;
	
	LCD_EN();       
	LCD_DEN();
	
	delay_ms(1);
}

void lcd_print(ULONG font_addr)
{                       
	UBYTE temp1;//, temp2, temp3;
	
	if(n_dsp==1)
	{          
		font_addr |= 0x2000;
	}
	else if(n_dsp==2)
	{
		font_addr |= 0x4000;
	}
	else if(n_dsp==3)
	{
		font_addr |= 0x6000;
	}
	else{
		font_addr &= 0xfff;
	}
	
	LCD_READY_CHK();
	
	temp1=(UBYTE)(font_addr&0xff); 
	
	
	P3DR=temp1;
	
	WR_LCD=0;  
	RS_LCD=1;
	LCD_EN();       
	LCD_DEN();
	
	LCD_READY_CHK();
	
	temp1=(UBYTE)(font_addr>>8);   
	
	P3DR=temp1;
	
	WR_LCD=0;
	RS_LCD=1;  
	LCD_EN();
	LCD_DEN();
	
	delay_ms(1);
}

void half_print(UBYTE font_addr)
{                       
	UBYTE temp1;//, temp2, temp3;
	
	font_addr |= 0x80;
	
	LCD_READY_CHK();
	
	temp1=(UBYTE)(font_addr&0xff); 
	
	P3DR=temp1;
	
	WR_LCD=0;  
	RS_LCD=1;
	
	LCD_EN();       
	LCD_DEN();
}

void CGRAM_INIT()
{
	UBYTE i=0,j=0;
	//----------------
	// CGRAM TEST                                                          
	//----------------
	LCD_CONT_REG_WRITE(LCD_EMR,0x06); // CGRAM select 
	
	// CGRAM first font write
	for(j=0;j<26;j++) {      
		LCD_CONT_REG_WRITE(LCD_RAR, 0x00+j); //0x0000
		CGRAM_ADDR(0x3f); //"¡á
	}
	
	// CGRAM second font write
	for(j=0;j<26;j++) {      
		LCD_CONT_REG_WRITE(LCD_RAR, 0x1a+j); 
		CGRAM_ADDR(CGRAM_DATA2[j]); // "¡à"  0x0001
	}   
	
	// CGRAM third font write
	for(j=0;j<26;j++) {      
		LCD_CONT_REG_WRITE(LCD_RAR, 0x34+j); 
		CGRAM_ADDR(CGRAM_DATA3[j]); // "¡à"  0x0002
	}   
	
	// CGRAM fourth font write
	for(j=0;j<26;j++) {      
		LCD_CONT_REG_WRITE(LCD_RAR, 0x4e+j); 
		CGRAM_ADDR(0x2a); // "¥²" 0x0003
	}   
	
	i=0;
	for(j=0;j<7;j++) 
	{      
		
		LCD_CONT_REG_WRITE(LCD_RAR, 0x68+i);   
		CGRAM_ADDR(0x3f); // "¡á"               //0x0004
		LCD_CONT_REG_WRITE(LCD_RAR, 0x68+i+1);   
		CGRAM_ADDR(0x3f); // "¡á"               //0x0004
		LCD_CONT_REG_WRITE(LCD_RAR, 0x68+i+2);   
		CGRAM_ADDR(0x00); //                   
		LCD_CONT_REG_WRITE(LCD_RAR, 0x68+i+3);   
		CGRAM_ADDR(0x00); //    
		i=j*4;;   
	}            
	LCD_CONT_REG_WRITE(LCD_EMR,0x04); // CGRAM select 
}




void main()
{
	UBYTE i=0,j=0,k=0,l=0;
	ULONG c_full;
	
	LCD_INIT();
	delay_ms(100);
	
	black();      
	
	delay_ms(1500);
	
	CGRAM_INIT();
	
#if 0
	// halft font test
	for(i=0; i<32 ; i++)
	{       
		half_xy(j,0);
		c_half=i*0x01;
		//printf("c_half=%02x, ",c_half);
		half_print(c_half);
		j++;
		delay_ms(10);    
	}    
	
	//printf("\r\n===============================\r\n");
	delay_ms(500);j=0;
	for(i=32; i<64; i++)
	{       
		half_xy(j,1);
		c_half=i*0x01;
		//printf("c_half=%02x, ",c_half);
		half_print(c_half);
		j++;
		delay_ms(10);
		
	}                                                 
	//printf("\r\n===============================\r\n");
	delay_ms(500);j=0;
	for(i=64; i<96; i++)
	{                          
		half_xy(j,0);
		c_half=i*0x01;
		//printf("c_half=%02x, ",c_half);
		half_print(c_half);
		j++;
		delay_ms(10);
		
	}
	//printf("\r\n===============================\r\n");
	delay_ms(500);j=0;        
	for(i=96; i<128 ; i++)
	{       
		half_xy(j,1);
		c_half=i*0x01;
		//printf("c_half=%02x, ",c_half);
		half_print(c_half);
		j++;
		delay_ms(10);
	}
#endif
	
	//cgram test
	CGRAM_INIT();
	
	do{
#if 1
		////////////////////////////////////////////
		// full charcter display
		////////////////////////////////////////////                         
		i=0;j=0;k=0;l=0;
		for(l=0; l<128 ; l++)            
		{              
			// line 1      
			for(i=k; i<k+16 ; i++)
			{    
				lcd_xy(j,0);
				c_full=i*0x1;
				lcd_print(c_full);
				j=j+0x02;
			}            
			k=k+16;
			j=0;
			
			// line 2
			for(i=k; i<k+16; i++)
			{       
				lcd_xy(j,1);
				c_full=i*0x1;
				lcd_print(c_full);
				j=j+0x02;
			}      
			
			k=k+16;                                
			delay_ms(500);
			j=0;
			l++;
		}
#endif
		
	}while(1);
}   


