/**************************************************************************//**
 * @file     main.c
 * @version  V1.00
 * $Revision: 1 $
 * $Date: 14/08/01 10:00p $
 * @brief    N572 SPI master demo sample source.
 *
 * @note
 * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
 *
 ******************************************************************************/
#include <stdio.h>
#include "N572.h"

#define TEST_COUNT 			(16)	    /* Test data count */

__align(4) uint32_t g_au32SourceData[TEST_COUNT];
__align(4) uint32_t g_au32DestinationData[TEST_COUNT];

void SPI_Init()
{
    /* Configure SPI_FLASH_PORT as a master(F065 only master mode), MSB first, SPI Mode-0 timing, clock is 8MHz */
	#if (__CHIP_SERIES__==__N572F072_SERIES__)
	SPI_Open(SPI0, SPI_MASTER, SPI_MODE_0, 8000000);
	#elif (__CHIP_SERIES__==__N572F065_SERIES__)
	SPI_Open(SPI0, SPI_MODE_0, 8000000);
	#endif

	SPI_SET_MSB_FIRST(SPI0);
	
	SPI_SET_SUSPEND_CYCLE(SPI0,5);
	
	SPI_DISABLE_BYTE_REORDER(SPI0);
	
	SPI_SET_DATA_WIDTH(SPI0,32);
	
	SPI_SET_TX_NUM(SPI0,SPI_TXNUM_ONE);
	
    /* Enable the automatic hardware slave select function */
    SPI_ENABLE_AUTOSS(SPI0,SPI_SS0,SPI_SS_ACTIVE_LOW);
}

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

    /* Enable External XTL32K */
    CLK_EnableXtalRC(CLK_PWRCTL_XTL32K_EN_Msk);
	
	/* 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);
	
	/* Enable PLL1 & PLL2 */
	CLK_SetPLL1Mode(PLL_NORMAL_MODE);
	CLK_SetPLL2Mode(PLL_NORMAL_MODE);
	
	/* Set PLL2 clock source & frequency */
	#if (__CHIP_SERIES__==__N572F072_SERIES__)
	CLK_SetPLL2( PLL2_SRC_PLL1_FOUT, PLL2_48M );
	#elif (__CHIP_SERIES__==__N572F065_SERIES__)
	CLK_SetPLL2( PLL2_SRC_PLL1_FOUT, NULL );
	#endif 
	
	/* Procedures to configure the HCLK from PLL2 */
	CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL2_FOUT,CLK_CLKDIV_HCLK(1));
	
	/* LDO On */
	#if (__CHIP_SERIES__==__N572F072_SERIES__)
	CLK_EnableLDO30();
	#endif

    /* Enable IP clock */
    CLK_EnableModuleClock(SPI0_MODULE);

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

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
    /* SPI0: GPA1=SSB0, GPA2=SCLK0, GPA3=MISO0, GPA4=MOSI0  */
	SYS->GPA_MFP  = (SYS->GPA_MFP & (~SYS_GPA_MFP_PA1MFP_Msk) ) | SYS_GPA_MFP_PA1MFP_SPI_SSB00;
	SYS->GPA_MFP  = (SYS->GPA_MFP & (~SYS_GPA_MFP_PA2MFP_Msk) ) | SYS_GPA_MFP_PA2MFP_SPI_SCLK0;
	SYS->GPA_MFP  = (SYS->GPA_MFP & (~SYS_GPA_MFP_PA3MFP_Msk) ) | SYS_GPA_MFP_PA3MFP_SPI_MISO0;	
	SYS->GPA_MFP  = (SYS->GPA_MFP & (~SYS_GPA_MFP_PA4MFP_Msk) ) | SYS_GPA_MFP_PA4MFP_SPI_MOSI0;	

	/* Reset IP module */
	SYS_ResetModule(SPI0_RST);
	
    /* Lock protected registers */
    SYS_LockReg();
}

int main()
{
	uint32_t u32Counter = 0;
	
    /* Init System, IP clock and multi-function I/O */
    SYS_Init();
	
	/* Initiate SPI */
	SPI_Init();
	
    printf("\n+------------------------------------------------------------------------+\n");
    printf("|                       SPI Driver Sample Code                           |\n");
    printf("+------------------------------------------------------------------------+\n");
    printf("Configure SPI0 as a master.\n");
    printf("SPI clock rate: %d Hz\n", SPI_GetBusClock(SPI0));
    printf("SPI controller will transfer %d data to a off-chip slave device.\n", TEST_COUNT);
    printf("In the meanwhile the SPI controller will receive %d data from the off-chip slave device.\n", TEST_COUNT);
    printf("After the transfer is done, the %d received data will be printed out.\n", TEST_COUNT);
    printf("The SPI master configuration is ready.\n");

    for(u32Counter=0; u32Counter<TEST_COUNT; u32Counter++)
    {
        g_au32SourceData[u32Counter] = 0x55AA5500 + u32Counter;
        g_au32DestinationData[u32Counter] = 0;
    }

    printf("Before starting the data transfer, make sure the slave device is ready.\n");
    printf("<<Press any key to start the transfer>>\n");
    getchar();
    printf("\n");
	
	/* Wait for transfer done */
    for(u32Counter=0; u32Counter<TEST_COUNT; u32Counter++)
	{
		SPI_WRITE_TX0( SPI0, g_au32SourceData[u32Counter] );
		SPI_GO(SPI0);
		while( SPI_IS_BUSY(SPI0) );
		g_au32DestinationData[u32Counter] = SPI_READ_RX0(SPI0);
	}
	
    printf("Received data:\n");
    for(u32Counter=0; u32Counter<TEST_COUNT; u32Counter++)
        printf("%d:\t0x%X\n", u32Counter, g_au32DestinationData[u32Counter]);
	
    printf("\nThe data transfer was done.\n"); 
    printf("\nExit SPI driver master sample code.\n");
    while(1);
}
