/*****************************************************/
/* Examples Program For "ET-ARM7 BASE LPC2103" Board */
/* Target MCU  : Philips ARM7-LPC2103                */
/*       	   : X-TAL : 19.6608 MHz                 */
/*             : Run Speed 58.9824MHz (With PLL)     */
/* Keil Editor : uVision3 V3.03a                     */
/* Compiler    : Keil CARM V2.50a		             */
/* Create By   : Eakachai Makarn (WWW.ETT.CO.TH)     */
/* Last Update : 17/April/2006                       */
/* Function    : Example Use Character LCD 16x2      */
/*****************************************************/
// LCD Routines for "ET-ARM7 BASE 210x" 
// Character 16x2 4-Bit Mode Interface 
// EN = P0.17
// RW = P0.18						   
// RS = P0.19
// D4 = P0.20						   
// D5 = P0.21						   
// D6 = P0.22						   
// D7 = P0.23						   

/* Warning Pull-Up 10K on EN_LCD Pin
    -> Pin GPIO0.17 (LCD_EN)
   LCD Not Stable(Not Work) if Not Pull-Up
*/						   

#include <LPC2103.H> 									// LPC2103 MPU Register
						   						  
// Define LCD PinIO Mask 
#define  LCD_EN     0x00020000   						// P0.17(0000 0000 0000 00x0 0000 0000 0000 0000)
#define  LCD_RW     0x00040000   						// P0.18(0000 0000 0000 0x00 0000 0000 0000 0000)
#define  LCD_RS     0x00080000   						// P0.19(0000 0000 0000 x000 0000 0000 0000 0000)
#define  LCD_D4     0x00100000   						// P0.20(0000 0000 000x 0000 0000 0000 0000 0000)
#define  LCD_D5     0x00200000   						// P0.21(0000 0000 00x0 0000 0000 0000 0000 0000)
#define  LCD_D6     0x00400000   						// P0.22(0000 0000 0x00 0000 0000 0000 0000 0000)
#define  LCD_D7     0x00800000   						// P0.23(0000 0000 x000 0000 0000 0000 0000 0000)
	
#define  LCD_DATA   (LCD_D7|LCD_D6|LCD_D5|LCD_D4)
#define  LCD_IOALL  (LCD_D7|LCD_D6|LCD_D5|LCD_D4|LCD_RS|LCD_RW|LCD_EN)

#define  lcd_rs_set() IOSET = LCD_RS	 				// RS = 1 (Select Instruction)
#define  lcd_rs_clr() IOCLR = LCD_RS					// RS = 0 (Select Data)
#define  lcd_rw_set() IOSET = LCD_RW					// RW = 1 (Read)
#define  lcd_rw_clr() IOCLR = LCD_RW					// RW = 0 (Write)
#define  lcd_en_set() IOSET = LCD_EN					// EN = 1 (Enable)
#define  lcd_en_clr() IOCLR = LCD_EN					// EN = 0 (Disable)

// 0000 0000 xxxx xxx0 0000 0000 0000 0000
#define  lcd_dir_write()  IODIR |= 0x00FE0000			// LCD Data Bus = Write
#define  lcd_dir_read()   IODIR &= 0xFF0EFFFF			// LCD Data Bus = Read 

#define  lcd_clear()          lcd_write_control(0x01)	// Clear Display
#define  lcd_cursor_home()    lcd_write_control(0x02)	// Set Cursor = 0
#define  lcd_display_on()     lcd_write_control(0x0E)	// LCD Display Enable
#define  lcd_display_off()    lcd_write_control(0x08)	// LCD Display Disable
#define  lcd_cursor_blink()   lcd_write_control(0x0F)	// Set Cursor = Blink
#define  lcd_cursor_on()      lcd_write_control(0x0E)	// Enable LCD Cursor
#define  lcd_cursor_off()     lcd_write_control(0x0C)	// Disable LCD Cursor
#define  lcd_cursor_left()    lcd_write_control(0x10)	// Shift Left Cursor
#define  lcd_cursor_right()   lcd_write_control(0x14)	// Shift Right Cursor
#define  lcd_display_sleft()  lcd_write_control(0x18)	// Shift Left Display
#define  lcd_display_sright() lcd_write_control(0x1C)	// Shift Right Display

/* pototype  section */
void lcd_init();										// Initial LCD
void lcd_out_data4(unsigned char);						// Strobe 4-Bit Data to LCD
void lcd_write_byte(unsigned char);						// Write 1 Byte Data to LCD
void lcd_write_control(unsigned char); 					// Write Instruction
void lcd_write_ascii(unsigned char); 					// Write LCD Display(ASCII)
void goto_cursor(unsigned char);						// Set Position Cursor LCD
void lcd_print(unsigned char*);							// Print Display to LCD
char busy_lcd(void);									// Read Busy LCD Status
void enable_lcd(void);	 								// Enable Pulse
void delay(unsigned long int);							// Delay Function
														
/* Main Program Start Here */
int main(void)
{      
  lcd_init();											// Initial LCD
  
  // Loop Print Message to LCD16 x 2 //
  while(1)	  											// Loop Continue
  {
    goto_cursor(0x00);									// Set Cursor Line-1
    lcd_print("ET-ARM7 BASE210x");						// Display LCD Line-1    
    goto_cursor(0x40);									// Set Cursor = Line-2
    lcd_print("Used MPU:LPC2103");						// Display LCD Line-2
    delay(5000000);										// Display Delay

	goto_cursor(0x00);									// Set Cursor Line-1
    lcd_print("32 Bit Processor");						// Display LCD Line-1    
    goto_cursor(0x40);									// Set Cursor = Line-2
    lcd_print("BY...ETT CO.,LTD");						// Display LCD Line-2
    delay(5000000);										// Display Delay  
  }  

}

/****************************/
/* Strobe 4-Bit Data to LCD */
/****************************/
void lcd_out_data4(unsigned char val)
{  
  IOCLR = (LCD_DATA);	  								// Reset 4-Bit Pin Data
  IOSET = (val<<20);  									// 0000:0000:dddd:RS,RW,EN,0:0000:0000:0000:0000 
}

/****************************/
/* Write Data 1 Byte to LCD */
/****************************/
void lcd_write_byte(unsigned char val)
{  
  lcd_out_data4((val>>4)&0x0F);							// Strobe 4-Bit High-Nibble to LCD
  enable_lcd();											// Enable Pulse
  
  lcd_out_data4(val&0x0F);				  				// Strobe 4-Bit Low-Nibble to LCD
  enable_lcd();											// Enable Pulse  

  while(busy_lcd());      								// Wait LCD Execute Complete  
}

/****************************/
/* Write Instruction to LCD */
/****************************/
void lcd_write_control(unsigned char val)
{ 
  lcd_rs_clr();											// RS = 0 = Instruction Select
  lcd_write_byte(val);									// Strobe Command Byte	    
}

/****************************/
/* Write Data(ASCII) to LCD */
/****************************/
void lcd_write_ascii(unsigned char c)
{  
  lcd_rs_set();											// RS = 1 = Data Select
  lcd_write_byte(c);		   							// Strobe 1 Byte to LCD    
}

/*******************************/
/* Initial 4-Bit LCD Interface */
/*******************************/
void lcd_init()
{
  unsigned int i;										// Delay Count
  
  PINSEL0  = 0x00000000;								// GPIO0 = I/O Function
  PINSEL1  = 0x00000000;  
  IODIR    = 0x00FE0000;								// P0[23..17] = Output
  for (i=0;i<50000;i++);								// Power-On Delay (15 mS)

  IOCLR = (LCD_IOALL);									// Reset (RS,RW,EN,4-Bit Data) Pin
  IOSET = (LCD_D5|LCD_D4);								// 0000:0000:(0,RS,RW,EN:0011):0000:0000:0000:0000
  enable_lcd();											// Enable Pulse
  for (i=0;i<10000;i++);								// Delay 4.1mS

  IOCLR = (LCD_IOALL);	  								// Reset (RS,RW,EN,4-Bit Data) Pin
  IOSET = (LCD_D5|LCD_D4);								// 0000:0000:(0,RS,RW,EN:0011):0000:0000:0000:0000
  enable_lcd();											// Enable Pulse
  for (i=0;i<100;i++);									// delay 100uS

  IOCLR = (LCD_IOALL);	  								// Reset (RS,RW,EN,4-Bit Data) Pin
  IOSET = (LCD_D5|LCD_D4);								// 0000:0000:(0,RS,RW,EN:0011):0000:0000:0000:0000
  enable_lcd();											// Enable Pulse
  while(busy_lcd());      								// Wait LCD Execute Complete
 
  IOCLR = (LCD_IOALL);	  								// Reset (RS,RW,EN,4-Bit Data) Pin
  IOSET = (LCD_D5);										// 0000:0000:(0,RS,RW,EN:0011):0000:0000:0000:0000
  enable_lcd();											// Enable Pulse
  while(busy_lcd());      								// Wait LCD Execute Complete
       
  lcd_write_control(0x28);  							// Function Set (DL=0 4-Bit,N=1 2 Line,F=0 5X7)
  lcd_write_control(0x0C);  							// Display on/off Control (Entry Display,Cursor off,Cursor not Blink)
  lcd_write_control(0x06);  							// Entry Mode Set (I/D=1 Increment,S=0 Cursor Shift)
  lcd_write_control(0x01);  							// Clear Display  (Clear Display,Set DD RAM Address=0) 
  for (i=0;i<100000;i++);								// Wait Command Ready
}

/***************************/
/* Set LCD Position Cursor */
/***************************/
void goto_cursor(unsigned char i)
{
  i |= 0x80;											// Set DD-RAM Address Command
  lcd_write_control(i);  
}

/************************************/
/* Print Display Data(ASCII) to LCD */
/************************************/
void lcd_print(unsigned char* str)
{
  int i;

  for (i=0;i<16 && str[i]!=0;i++)  						// 16 Character Print
  {
    lcd_write_ascii(str[i]);							// Print Byte to LCD
  }
}

/******************/
/* Wait LCD Ready */
/******************/

char busy_lcd(void)
{
  unsigned long busy_status;							// Busy Status Read
  unsigned int i;										// Delay Count

  lcd_dir_read();										// LCD Data Bus = Read
  lcd_rs_clr();		 									// Instruction Select
  lcd_rw_set(); 										// Read Direction
  lcd_en_set();											// Start Read Busy

  for (i=0;i<100;i++);	  								// Delay Before Read
  busy_status = (IOPIN & 0x00800000);					// Read LCD Data(0000:0000:dddd:RS,RW,EN,0:0000:0000:0000:0000)

  if(busy_status == 0x00800000)  						// Read & Check Busy Flag
  {
    lcd_en_clr();  										// Disable Read
	lcd_rw_clr();										// Default = Write Direction
	lcd_dir_write();									// LCD Data Bus = Write
    return 1;											// LCD Busy Status
  }
  else
  {
    lcd_en_clr();  										// Disable Read
	lcd_rw_clr();										// Default = Write Direction
	lcd_dir_write();									// LCD Data Bus = Write
    return 0;											// LCD Ready Status
  }
}


/***********************/
/* Enable Pulse to LCD */
/***********************/
void enable_lcd(void)	 								// Enable Pulse
{
  unsigned int i;										// Delay Count
  lcd_en_set();  										// Enable ON
  for (i=0;i<50;i++);
  lcd_en_clr();  										// Enable OFF 
}

/***********************/
/* Delay Time Function */
/*    1-4294967296     */
/***********************/
void delay(unsigned long int count1)
{
  while(count1 > 0) {count1--;}							// Loop Decrease Counter	
}


