/*****************************************************/
/* Examples Program For "ET-ARM7 BASE LPC2106" Board */
/* Target MCU  : Philips ARM7-LPC2106                */
/*       	   : 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    : SelfTest For ET-BASE ARM LPC2106    */
/*****************************************************/
// 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						   
						   
#include <LPC210x.H> 										// LPC2106 MPU Register
#include <stdio.h>											// For Used Function printf 

#define  MASKSEC 	0x3F  									// Second 00..59   00000000:00000000:00xxxxxx
#define  MASKMIN 	0x3F00									// Minute 00..59   00000000:00xxxxxx:00000000
#define  MASKHR  	0x1F0000								// Hour 00..23	   000xxxxx:00000000:00000000
						   						  
// 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 init_serial0 (void); 									// Initil UART-0
int putchar (int ch);  										// Put Char to UART-0
int getchar (void);  										// Get Char From Uart-0

void init_serial1 (void); 									// Initil UART-1
int putchar1 (int ch);  									// Put Char to UART-1
int getchar1 (void);  										// Get Char From UART-1

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

void test_lcd(void);								   		// Test LCD 16x2
void test_rtc(void);										// Test Internal RTC
void test_uart1(void);										// Test RS232-2
void test_auto(void);										// Test GPIO(Auto)
void test_manual(void);										// Test GPIO(Manual)
														
/* Main Program Start Here */
int main(void)
{  
  char data;
  init_serial0();		   									// Initilial UART0 = 9600,N,8,1

  printf("\n\n\n");
  printf("****************************\n");
  printf("***ET-ARM7 BASE (LPC2106)***\n");
  printf(">>>>> SYSTEM SELF TEST <<<<<\n");   
  printf("1. Test LCD(Char16x2)\n");
  printf("2. Test RTC(Internal LPC2106)\n");
  printf("3. Test UART-2(RS232-2)\n");
  printf("4. Test LPC2106 GPIO(Auto)\n");
  printf("5. Test LPC2106 GPIO(Manual)\n");
  printf("****************************\n");
  printf("\n");
  printf("Select Choice(1...5)......");

  // Loop Print Out Message to UART0 //
  while(1)													// Loop Continue
  {
    data = getchar(); 										// Get Choice
	switch (data)
	{
	  case '1' : printf("\n\n");
	             printf("Test LCD 16x2\n");	 
				 test_lcd();								// Test LCD 16x2
	             break;

	  case '2' : printf("\n\n");
	             printf("Test RTC(Internal LPC2106)\n");
				 test_rtc();								// Test Internal RTC
	             break;

	  case '3' : printf("\n\n");
	             printf("Test UART-2(RS232-2)\n");	 
				 test_uart1();								// Test RS232-2
	             break;

	  case '4' : printf("\n\n");
	             printf("Test Auto All GPIO Output\n");
				 test_auto();					 			// Test GPIO(Auto)
				 break;						  		

	  case '5' : printf("\n\n");
	             printf("Test Manual All GPIO [Output]\n");
				 printf("Press Any Key For Test Output\n");
				 test_manual();								// Test GPIO(Manual)
				 break;
	}

  }

}

/******************************/
/* Initial UART0 = 9600,N,8,1 */
/* VPB(pclk) = 29.4912 MHz    */
/******************************/
void init_serial0 (void)  
{
  PINSEL0 &= 0xFFFFFFF0;									// Reset P0.0,P0.1 Pin Config
  PINSEL0 |= 0x00000001;									// Select P0.0 = TxD(UART0)
  PINSEL0 |= 0x00000004;									// Select P0.1 = RxD(UART0)

  U0LCR &= 0xFC;											// Reset Word Select(1:0)
  U0LCR |= 0x03;											// Data Bit = 8 Bit
  U0LCR &= 0xFB;											// Stop Bit = 1 Bit
  U0LCR &= 0xF7;											// Parity = Disable
  U0LCR &= 0xBF;											// Disable Break Control
  U0LCR |= 0x80;											// Enable Programming of Divisor Latches

  // U0DLM:U0DLL = 29.4912MHz / [16 x Baud]
  //             = 29.4912MHz / [16 x 9600]
  //             = 192 = 0x00C0
  U0DLM = 0x00;												// Program Divisor Latch(192) for 9600 Baud
  U0DLL = 0xC0;

  U0LCR &= 0x7F;											// Disable Programming of Divisor Latches

  U0FCR |= 0x01;											// FIF0 Enable
  U0FCR |= 0x02;											// RX FIFO Reset
  U0FCR |= 0x04;											// TX FIFO Reset
  U0FCR &= 0x3F;                      
}

/****************************/
/* Write Character To UART0 */
/****************************/
int putchar (int ch)  
{                  
  if (ch == '\n')  
  {
    while (!(U0LSR & 0x20));  								// Wait TXD Buffer Empty
    U0THR = 0x0D;                          					// Write CR
  }
  while (!(U0LSR & 0x20));									// Wait TXD Buffer Empty
  return (U0THR = ch);										// Write Character
}

/*****************************/
/* Read Character From UART0 */
/*****************************/
int getchar (void)  
{                    
  while (!(U0LSR & 0x01));									// Wait RXD Receive Data Ready
  return (U0RBR);											// Get Receice Data & Return
}

/******************************/
/* Initial UART1 = 9600,N,8,1 */
/* VPB(pclk) = 29.4912 MHz    */
/******************************/
void init_serial1 (void)  
{
  PINSEL0 &= 0xFFF0FFFF;									// Reset P0.8,P0.9 Pin Config
  PINSEL0 |= 0x00010000;									// Select P0.8 = TxD(UART1)
  PINSEL0 |= 0x00040000;									// Select P0.9 = RxD(UART1)

  U1LCR &= 0xFC;											// Reset Word Select(1:0)
  U1LCR |= 0x03;											// Data Bit = 8 Bit
  U1LCR &= 0xFB;											// Stop Bit = 1 Bit
  U1LCR &= 0xF7;											// Parity = Disable
  U1LCR &= 0xBF;											// Disable Break Control
  U1LCR |= 0x80;											// Enable Programming of Divisor Latches

  // U0DLM:U0DLL = 29.4912MHz / [16 x Baud]
  //             = 29.4912MHz / [16 x 9600]
  //             = 192 = 0x00C0
  U1DLM = 0x00;												// Program Divisor Latch(192) for 9600 Baud
  U1DLL = 0xC0;

  U1LCR &= 0x7F;											// Disable Programming of Divisor Latches

  U1FCR |= 0x01;											// FIF0 Enable
  U1FCR |= 0x02;											// RX FIFO Reset
  U1FCR |= 0x04;											// TX FIFO Reset
  U1FCR &= 0x3F;                       
}

/****************************/
/* Write character to UART1 */
/****************************/
int putchar1 (int ch)  
{                  
  if (ch == '\n')  
  {
    while (!(U1LSR & 0x20));								// Wait TXD Buffer Empty
    U1THR = 0x0D;                          					// Write CR
  }
  while (!(U1LSR & 0x20)); 									// Wait TXD Buffer Empty
  return (U1THR = ch);						    			// Write Character
}

/*****************************/
/* Read character from UART1 */
/*****************************/
int getchar1 (void)  
{                    
  while (!(U1LSR & 0x01));	 								// Wait RXD Receive Data Ready
  return (U1RBR);											// Get Receice Data & Return
}

/*******************************/
/* 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
}

/****************************/
/* 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)
{  
  unsigned int i;											// Delay Count

  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  
  for (i=0;i<10000;i++);									// Wait Command Ready
}

/****************************/
/* 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    
}


/***************************/
/* 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	
}


/*********************/
/* Test Internal RTC */
/*********************/
void test_rtc(void)
{    
  unsigned char Hour,Minute,Second,Last_Second;				// RTC Buffer Data
  printf("\n\n\nET-ARM7 BASE LPC2106...TEST RTC\n"); 		// Call prinff Function

  // PREINT  = (PCLK/32768) - 1
  //         = (29.4912MHz/32768) - 1
  //         = 900-1
  //         = 899
  // PREFRAC = PCLK - ((PREINT + 1) x 32768 )
  //         = 29.49152MHz - ((899 + 1) x 32768)
  //         = 0
  PREINT  = 0x00000899;										//Set RTC Prescaler For PCLK 29.49152 MHz
  PREFRAC = 0x00000000;

  // Initial Internal RTC Function
  CCR &= 0x00;												// Reset All Bit
  CCR |= 0x02; 												// Reset Clock	  (0000 0010)
  CCR &= 0xFD;												// Release Reset  (1111 1101)
  CCR |= 0x01;												// Start RTC Clock	

  // Setup Start Time For RTC = 00:00:00
  HOUR = 0x00;
  MIN  = 0x00;
  SEC  = 0x00;
  Last_Second = 0x00;
 
  // Start Test Read RTC and Display on UART0 //
  while(1)
  { 
    do 														// Repeat Get Second until Second Change
	{		
	  Hour   = (CTIME0 & MASKHR)>>16;						// Read Hour
	  Minute = (CTIME0 & MASKMIN)>>8;		 				// Read Minute
	  Second = CTIME0 & MASKSEC;		  					// Read Second
    }
    while(Last_Second == Second);							// Repeat if Second Not Change
	
    Last_Second = Second;									// Update Current Second
          
    //************************************//
    // Display Clock = Hour:Minute:Second //
    //************************************//
    printf("\rReal Time Clock = ");							// Print Message String 
  	printf(" %2d : %2d : %2d",Hour,Minute,Second);	 
  }
}


/**********************/
/* Test Character LCD */
/**********************/
/* Main Program Start Here */
void test_lcd(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 BASE2106");							// Display LCD Line-1    
    goto_cursor(0x40);										// Set Cursor = Line-2
    lcd_print("Used MPU:LPC2106");							// Display LCD Line-2
    delay(10000000);										// 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(10000000);										// Display Delay  
  }  

}

/************************/
/* Test UART-1(RS232-2) */
/************************/
void test_uart1(void)
{  
  char data;												// Char Buffer For UART
  init_serial1();		   									// Initilial UART1 = 9600,N,8,1
  printf("ET-ARM7 BASE LPC2106...TEST UART-1\n"); 			// Call printf Function
  printf("Connect RS232-2 Cable For Test\n"); 	
  printf("Press Any Key For Test...UART-1\n");

  while(1)													// Loop Continue
  {
    data = getchar1();										// Wait Receive Byte From UART-0
	putchar1(data);											// Echo Data to UART-0
  }													
}

/********************/
/* Test GPIO (Auto) */
/********************/
void test_auto(void)
{
  unsigned long int LED; 									// LED Output Status Buffer

  // Initial all GPIO-0 = Output
  // Reserve P0.0 = TXD(UART0)
  // Reserve P0.1 = RXD(UART0)
  // [xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx--]    
  PINSEL0 = 0x00000000;										// Makesure GPIO0[00..15] = GPIO Function
  PINSEL1 = 0x00000000;										// Makesure GPIO0[16..31] = GPIO Function
  IODIR   = 0xFFFFFFFC; 						         	// Set all GPIO-0[02..31] = Output
  IOSET   = 0xFFFFFFFC;                                  	// Set all GPIO-0 Output Pin(OFF LED)  
 
  // Loop Test Output GPI0-0 //
  while(1)													// Loop Continue
  {    	
	// GPIO0.31 <-- GPIO0.2
    for (LED = 0x00000004; LED < 0x80000000; LED <<= 1)		// Shift Left GPIO-0 (Right <- Left)
    { 
	  IOCLR = LED;											// Clear Output Pin (ON LED)
      delay(10000000);										// Display Delay
	  IOSET = LED;                                   		// Set Output Pin (OFF LED)	  
    }  
	  
	// GPIO0.31 ---> GPIO0.2
	for (LED = 0x80000000; LED > 0x00000004; LED >>= 1)		// Shift Right GPIO-0(Right -> Left)
    { 
	  IOCLR = LED;											// Clear Output Pin (ON LED)
      delay(10000000);										// Display Delay
	  IOSET = LED;                                   		// Set Output Pin (OFF LED)
    }  	  
  }   
}

/**********************/
/* Test GPIO (Manual) */
/**********************/
void test_manual(void)
{
  unsigned long int LED; 									// LED Output Status Buffer
  char data;												// Char Buffer For UART

  // Initial all GPIO-0 = Output
  // Reserve P0.0 = TXD(UART0)
  // Reserve P0.1 = RXD(UART0)
  // [xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx--]    
  PINSEL0 = 0x00000000;										// Makesure GPIO0[00..15] = GPIO Function
  PINSEL1 = 0x00000000;										// Makesure GPIO0[16..31] = GPIO Function
  IODIR   = 0xFFFFFFFC; 						         	// Set all GPIO-0[02..31] = Output
  IOSET   = 0xFFFFFFFC;                                  	// Set all GPIO-0 Output Pin(OFF LED)  
  init_serial0();		   									// Initilial UART0 = 9600,N,8,1

  // Loop Test Output GPI0-0 //
  while(1)													// Loop Continue
  {    	
	// GPIO0.31 <-- GPIO0.2
    for (LED = 0x00000004; LED < 0x80000000; LED <<= 1)		// Shift Left GPIO-0 (Right <- Left)
    { 
	  IOCLR = LED;											// Clear Output Pin (ON LED)
      data = getchar(); 									// Get Choice
	  IOSET = LED;                                   		// Set Output Pin (OFF LED)	  
    }  
	  
	// GPIO0.31 ---> GPIO0.2
	for (LED = 0x80000000; LED > 0x00000004; LED >>= 1)		// Shift Right GPIO-0(Right -> Left)
    { 
	  IOCLR = LED;											// Clear Output Pin (ON LED)
      data = getchar(); 									// Get Choice
	  IOSET = LED;                                   		// Set Output Pin (OFF LED)
    }  	  
  }   
}



	       

