/**************************************************************************//**
 * @file     main.c
 * @version  V1.00
 * $Revision: 1 $
 * $Date: 14/08/01 10:00p $
 * @brief    N572 SPI slave demo sample source.
 *
 * @note
 * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
 *
 ******************************************************************************/
#include <stdio.h>
#include <string.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 SPI1 as a slave, MSB first, SPI Mode-0 timing, clock is from master provide */
    SPI_Open(SPI1, SPI_SLAVE, SPI_MODE_0, 0);

	SPI_SET_MSB_FIRST(SPI1);
	
	SPI_SET_SUSPEND_CYCLE(SPI1,2);
	
	SPI_DISABLE_BYTE_REORDER(SPI1);
	
	SPI_SET_DATA_WIDTH(SPI1,32);
	
	SPI_SET_TX_NUM(SPI1,SPI_TXNUM_ONE);
	
    /* Disable the automatic hardware slave select function */
	SPI_DISABLE_AUTOSS(SPI1);
	
	SPI_SET_SS(SPI1,SPI_SS0);
	
	SPI_SET_SLAVE_ACTIVE_LEVEL(SPI1,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 */
	CLK_SetPLL2( PLL2_SRC_PLL1_FOUT, PLL2_48M );
	
	/* Procedures to configure the HCLK from internal RC */
	CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL2_FOUT,CLK_CLKDIV_HCLK(1));
	
	/* LDO On */
	CLK_EnableLDO30();

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

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

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
    /* SPI1: GPA1=SSB0, GPA2=SCLK0, GPA3=MISO0, GPA4=MOSI0  */
	SYS->GPB_MFP  = (SYS->GPB_MFP & (~SYS_GPB_MFP_PB1MFP_Msk) ) | SYS_GPB_MFP_PB1MFP_SPI_SSB10;
	SYS->GPB_MFP  = (SYS->GPB_MFP & (~SYS_GPB_MFP_PB2MFP_Msk) ) | SYS_GPB_MFP_PB2MFP_SPI_SCLK1;
	SYS->GPB_MFP  = (SYS->GPB_MFP & (~SYS_GPB_MFP_PB3MFP_Msk) ) | SYS_GPB_MFP_PB3MFP_SPI_MISO1;	
	SYS->GPB_MFP  = (SYS->GPB_MFP & (~SYS_GPB_MFP_PB4MFP_Msk) ) | SYS_GPB_MFP_PB4MFP_SPI_MOSI1;	

	/* Reset IP module */
	SYS_ResetModule(SPI1_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 SPI1 as a slave.\n");
	printf("Pin define: PB1=SSB0, PB2=SCLK, PB3=MISO1, PB4=MOSI1\n");
    printf("SPI controller will transfer %d data to a off-chip master device.\n", TEST_COUNT);
    printf("In the meanwhile the SPI controller will receive %d data from the off-chip master device.\n", TEST_COUNT);
    printf("After the transfer is done, the %d received data will be printed out.\n", TEST_COUNT);
    printf("The SPI slave configuration is ready.\n");

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

    printf("<<Press any key if the master device configuration is ready>>\n");
    getchar();
    printf("\n");
	
	/* Wait for transfer done */
    for(u32Counter=0; u32Counter<TEST_COUNT; u32Counter++)
	{
		SPI_WRITE_TX0( SPI1, g_au32SourceData[u32Counter] );
		SPI_GO(SPI1);
		while( SPI_IS_BUSY(SPI1) );
		g_au32DestinationData[u32Counter] = SPI_READ_RX0(SPI1);
	}
	
    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 slave sample code.\n");
    while(1);
}
