/* *********************************************************
               Function declarations
  ********************************************************* */

void Initialize(void);
void feed(void);

void IRQ_Routine (void)   __attribute__ ((interrupt("IRQ")));
void FIQ_Routine (void)   __attribute__ ((interrupt("FIQ")));
void SWI_Routine (void)   __attribute__ ((interrupt("SWI")));
void UNDEF_Routine (void) __attribute__ ((interrupt("UNDEF")));

/**********************************************************
                  Header files
 **********************************************************/
#include "LPC210x.h"

#define FOSC		14745000
#define PLL_M		4	

#define		ON		1
#define		OFF		0

#define WAIT100MS	10
#define WAIT1S		100


#define TxTCR_COUNTER_ENABLE (1<<0)
#define TxTCR_COUNTER_RESET  (1<<1)
#define TxMCR_INT_ON_MR0     (1<<0)
#define TxMCR_RESET_ON_MR0   (1<<1)

#define VICVectCntl0_ENABLE (1<<5)
#define VIC_Channel_Timer0  4

/**********************************************************
                  Global Variables
 **********************************************************/
	
#define TxIR_MR0_FLAG        (1<<0)

volatile unsigned long timeval;


/* Setup Timer0 Compare-Match Interrupt         */
/* no prescaler timer runs at cclk = FOSC*PLL_M */
static void init_timer (void) {
	
	TIMER0_MR0 = ((FOSC*PLL_M)/(1000/10))-1;     		// Compare-hit at 10mSec (-1 reset "tick")
	TIMER0_MCR = TxMCR_INT_ON_MR0 | TxMCR_RESET_ON_MR0; 	// Interrupt and Reset on MR0
	TIMER0_TCR = TxTCR_COUNTER_ENABLE;            		// Timer0 Enable

	//VICVectAddr0 = (unsigned long)tc0_cmp;   		// set interrupt vector in 0
	VICVectAddr0 = (unsigned long)IRQ_Routine;   		// set interrupt vector in 0
	VICVectCntl0 = VICVectCntl0_ENABLE | VIC_Channel_Timer0; // use it for Timer 0 Interrupt:
	VICIntEnable = (1<<VIC_Channel_Timer0);    		// Enable Timer0 Interrupt
}


static void wait (unsigned long delay)  
{
  unsigned long i;

  i = timeval + delay;
  while ( i != timeval);        
}


/**********************************************************
                       MAIN
**********************************************************/

int	main (void) {
	
	int		i, j;		// loop counter (stack variable)
		  
	// Initialize the system
	Initialize();
	
	// set io pins for led P0.7
	IODIR |= 0x00000080;	// pin P0.7 is an output, everything else is input after reset
	
	IOSET =  0x00000080;	// led off
	

	// UART initialization
	UART0Initialize(9600);
	
	init_timer();
 	
	// endless loop to toggle the red  LED P0.7
	while (1) {
		
		
		IOSET =  0x00000080;	// led off
		wait(WAIT100MS);
		IOCLR =  0x00000080;	// led on
		wait(WAIT100MS);
		
	}
	
	
	
	
}



/**********************************************************
                      Initialize
**********************************************************/

#define PLOCK 0x400

void Initialize(void)  {
	
 
	// 				Setting the Phased Lock Loop (PLL)
	//               ----------------------------------
	//
	// Olimex LPC-P2106 has a 14.7456 mhz crystal
	//
	// We'd like the LPC2106 to run at 53.2368 mhz (has to be an even multiple of crystal)
	// 
	// According to the Philips LPC2106 manual:   M = cclk / Fosc	where:	M    = PLL multiplier (bits 0-4 of PLLCFG)
	//																		cclk = 53236800 hz
	//																		Fosc = 14745600 hz
	//
	// Solving:	M = 53236800 / 14745600 = 3.6103515625
	//			M = 4 (round up)
	//
	//			Note: M - 1 must be entered into bits 0-4 of PLLCFG (assign 3 to these bits)
	//
	//
	// The Current Controlled Oscilator (CCO) must operate in the range 156 mhz to 320 mhz
	//
	// According to the Philips LPC2106 manual:	Fcco = cclk * 2 * P    where:	Fcco = CCO frequency 
	//																			cclk = 53236800 hz
	//																			P = PLL divisor (bits 5-6 of PLLCFG)
	//
	// Solving:	Fcco = 53236800 * 2 * P
	//			P = 2  (trial value)
	//			Fcco = 53236800 * 2 * 2
	//			Fcc0 = 212947200 hz    (good choice for P since it's within the 156 mhz to 320 mhz range
	//
	// From Table 19 (page 48) of Philips LPC2106 manual    P = 2, PLLCFG bits 5-6 = 1  (assign 1 to these bits)
	//
	// Finally:      PLLCFG = 0  01  00011  =  0x23
	//
	// Final note: to load PLLCFG register, we must use the 0xAA followed 0x55 write sequence to the PLLFEED register
	//             this is done in the short function feed() below
	//
   
	// Setting Multiplier and Divider values
  	PLLCFG=0x23;
  	feed();
  
	// Enabling the PLL */	
	PLLCON=0x1;
	feed();
  
	// Wait for the PLL to lock to set frequency
	while(!(PLLSTAT & PLOCK)) ;
  
	// Connect the PLL as the clock source
	PLLCON=0x3;
	feed();
  
	// Enabling MAM and setting number of clocks used for Flash memory fetch (4 cclks in this case)
	MAMCR=0x2;
	MAMTIM=0x4;

	/* Initialize MEMAP - re-map vector table to RAM */
	//MEMMAP = 0x02;
  
	// Setting peripheral Clock (pclk) to System Clock (cclk)
	VPBDIV=0x1;
}


void feed(void)
{
  PLLFEED=0xAA;
  PLLFEED=0x55;
}






/*  Stubs for various interrupts (may be replaced later)  */
/*  ----------------------------------------------------  */

void __attribute__ ((interrupt("IRQ"))) IRQ_Routine (void) {
	
	timeval++;
	TIMER0_IR = TxIR_MR0_FLAG; 	// Clear interrupt flag by writing 1 to Bit 0
	VICVectAddr = 0;       		// Acknowledge Interrupt (rough?)
	
}

void FIQ_Routine (void)  {
	while (1) ;	
}


void SWI_Routine (void)  {
	while (1) ;	
}


void UNDEF_Routine (void) {
	while (1) ;	
}











  


