/**************************************************************************//**
 * @file     main.c
 * @version  V1.00
 * $Revision: 1 $
 * $Date: 14/07/15 2:52p $
 * @brief    N572 General Purpose I/O Driver Sample Code
 *
 * @note
 * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
 *
 ******************************************************************************/
#include <stdio.h>
#include "N572.h"

volatile uint8_t u8Counter = 0;
uint8_t u8Option = 0;

void TMR0_IRQHandler(void)
{
    printf("Timer IRQ handler run counter = %d\n", ++u8Counter );
    TIMER_ClearIntFlag(TIMER0);	
}

void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Unlock protected registers */
    SYS_UnlockReg();

    // Enable Internal RC
#if( __CHIP_SERIES__ == __N572F065_SERIES__ )	
    CLK_EnableXtalRC(CLK_PWRCTL_OSC24M_EN_Msk);
#endif
#if( __CHIP_SERIES__ == __N572F072_SERIES__ )	
    CLK_EnableXtalRC(CLK_PWRCTL_OSC48M_EN_Msk);
#endif
	
    // Enable External XTL32K
    CLK_EnableXtalRC(CLK_PWRCTL_XTL32K_EN_Msk);

		// Enable PLL1 & PLL2
		CLK_SetPLL1Mode(PLL_NORMAL_MODE);
		CLK_SetPLL2Mode(PLL_NORMAL_MODE);
	
		// Select PLL2 input source and frequence
#if( __CHIP_SERIES__ == __N572F065_SERIES__ )	
		CLK_SetPLL2(PLL2_SRC_PLL1_FOUT, NULL); // 32K -> PLL1(6M) -> PLL2(48M)
#endif
#if( __CHIP_SERIES__ == __N572F072_SERIES__ )	
		CLK_SetPLL2(PLL2_SRC_PLL1_FOUT, PLL2_48M);
#endif

		// Set RAM wait state
		SYS_SET_RAM_WAIT_STATE(SYS_IPRST0_RAMWS_ZERO_WAIT);
	
    // Set flash memory wait state
		SYS_SET_CPU_WAIT_STATE(SYS_IPRST0_CPUWS_1HCLK_WAIT);

		// Procedures to configure the HCLK from internal RC
#if( __CHIP_SERIES__ == __N572F065_SERIES__ )	
	    //CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_XTL_32K,CLK_CLKDIV_HCLK(1));
			//CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL1_FOUT,CLK_CLKDIV_HCLK(1));
			CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL2_FOUT,CLK_CLKDIV_HCLK(1));
			//CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_RC_24M,CLK_CLKDIV_HCLK(1));
#endif
#if( __CHIP_SERIES__ == __N572F072_SERIES__ )	
	    //CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_XTL_32K,CLK_CLKDIV_HCLK(1));
			//CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL1_FOUT,CLK_CLKDIV_HCLK(1));
			CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL2_FOUT,CLK_CLKDIV_HCLK(1));
			//CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_RC_48M,CLK_CLKDIV_HCLK(1));
		#endif
	
    /* Enable IP clock */
    CLK_EnableModuleClock(TMR0_MODULE);

    /* Select IP clock source */
    CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_HCLK, 0);

		// Update System Core Clock
    // User can use SystemCoreClockUpdate() to calculate SystemCoreClock.
    SystemCoreClockUpdate();

    // Lock protected registers
    SYS_LockReg();

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
}

/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function                                                                                           */
/*---------------------------------------------------------------------------------------------------------*/
int main (void)
{
    /* Lock protected registers */
    if(SYS->REGLCTL == 1) // In end of main function, program issued CPU reset and write-protection will be disabled.
        SYS_LockReg();

		/* Init System, IP clock and multi-function I/O
       In the end of SYS_Init() will issue SYS_LockReg()
       to lock protected register. If user want to write
       protected register, please issue SYS_UnlockReg()
       to unlock protected register if necessary */
    SYS_Init();

    printf("\n\nCPU @ %dHz\n", SystemCoreClock);

    printf("+-------------------------------------+ \n");
    printf("|           Timer Driver Sample Code  | \n");
    printf("+-------------------------------------+ \n");

    while(1) 
		{
				printf("\nSelect Test Item(1-2):\n");
				printf("Key 1: Timer IRQ Handeler.\n");
				printf("Key 2: Timer Delay 2 sec.\n");
				
				u8Option = getchar();

				switch(u8Option)
				{
						case '1':
                printf("\nStart to Timer IRQ Handeler test.\n\n" );
                
                TIMER_Open( TIMER0, TIMER_PERIODIC_MODE, 10); // Using TIMER0 PERIODIC_MODE , Freq=10Hz.
                u8Counter = 0;
								
                TIMER_Start(TIMER0); // Start Timer 0
                
                TIMER_EnableInt(TIMER0); // Enable timer interrupt
                NVIC_EnableIRQ(TMR0_IRQn);	
                
								while( u8Counter < 20 ); // Wait interrupt happened 20 times.
								
								TIMER_Close(TIMER0); // Close timer for next test.
						
                printf("\nTimer IRQ Handeler test complete.\n" );			
								break;
						case '2':
                TIMER_Delay( TIMER0, 333333);	 // Delay 333.333 milli second via timer0.
                TIMER_Delay( TIMER0, 333333);	 // Delay 333.333 milli second via timer0.
                TIMER_Delay( TIMER0, 333333);	 // Delay 333.333 milli second via timer0.
                TIMER_Delay( TIMER0, 333333);	 // Delay 333.333 milli second via timer0.
                TIMER_Delay( TIMER0, 333333);	 // Delay 333.333 milli second via timer0.
                TIMER_Delay( TIMER0, 333333);	 // Delay 333.333 milli second via timer0.

								printf("\nTimer Delay 2 sec test complete.\n" );
								break;
				}				
    }
}
