/******************** (C) COPYRIGHT 2023 SONiX *******************************
* COMPANY:		SONiX
* DATE:				2023/12
* AUTHOR:			SA1
* IC:					SN32F240C
*____________________________________________________________________________
*	REVISION	Date				User		Description
*	1.0				2023/12/08	SA1			1. First version released
*																2. Compatible to CMSIS DFP Architecture in Keil MDK v5.X (http://www.keil.com/dd2/pack/)
*																3. Run HexConvert to generate bin file and show checksum after building.
*_____________________________________________________________________________
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS TIME TO MARKET.
* SONiX SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL 
* DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE
* AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN 
* IN CONNECTION WITH THEIR PRODUCTS.
*****************************************************************************/

/*_____ I N C L U D E S ____________________________________________________*/
#include <SN32F240C.h>
#include <SN32F200_Def.h>
#include ".\Interface\SPI\SPI.h"
#include ".\Utility\Utility.h"


/*_____ D E C L A R A T I O N S ____________________________________________*/
void	NotPinOut_GPIO_init(void);
void PFPA_Init(void);

/*_____ D E F I N I T I O N S ______________________________________________*/
#define		SPI_TEST_CNT		32

uint16_t	hwSPI_Tx_Fifo[SPI_TEST_CNT];
uint16_t	hwSPI_Rx_Fifo[SPI_TEST_CNT];

#ifndef	SN32F248C					//Do NOT Remove or Modify!!!
	#error Please install SONiX.SN32F2_DFP.1.3.6.pack or version >= 1.2.9
#endif
#define	PKG		SN32F248C		//User SHALL modify the package on demand (SN32F248C, SN32F247C, SN32F246C, SN32F2451C) 

/*_____ M A C R O S ________________________________________________________*/


/*_____ F U N C T I O N S __________________________________________________*/
void SPI0_NBytesTxRx(uint32_t N_Bytes);


/*****************************************************************************
* Function		: main
* Description	: SPI0 is master. (Connect MISO0 & MOIS0) 
								Exapmle Mode is SPI (CPHA=0, CPOL=0, MLS=0).
								Change mode by setting FORMAT, CPHA, CPOL, MLSB.
* Input			: None
* Output		: None
* Return		: None
* Note			: Connect MISO0 and MOSI0 
*****************************************************************************/
int	main (void)
{
	uint32_t	i=0;
	uint32_t	j=0;	

	PFPA_Init();										//User shall set PFPA if used, do NOT remove!!!
	//User can configure System Clock with Configuration Wizard in system_SN32F240C.c
	SystemInit();
	SystemCoreClockUpdate();				//Must call for SN32F240C, Please do NOT remove!!!

	//Note: User can refer to ClockSwitch sample code to switch various HCLK if needed.
	//1. User SHALL define PKG on demand.
	//2. User SHALL set the status of the GPIO which are NOT pin-out to input pull-up.
	NotPinOut_GPIO_init();
	//--------------------------------------------------------------------------
	//User Code starts HERE!!!

	//System Interface Init
	SPI0_Init();

	//Write TX FIFO
	for(i=0;i<SPI_TEST_CNT;i++)
	{
		hwSPI_Tx_Fifo[i] = i;
	}	

	//Start Transmission
	j = SPI_TEST_CNT;

	SPI0_NBytesTxRx(j);

	//Check data 
	for(i=0;i<j;i++)
	{
		if(hwSPI_Tx_Fifo[i] != hwSPI_Rx_Fifo[i])
		{
			while(1);	//Error
		}		
	}
	
	while(1); //Pass
}


/***************************************************************************************************************
* Function		: SIP0_NBytesTxRx
* Description	:
* Input			: hwSPI_Tx_Fifo
* Output		: hwSPI_Rx_Fifo
* Return		: None
* Note			: Avoid all of the interrupts which may make FW can't fill in TX FIFO (SN_SPI0->DATA=...) in time.
***************************************************************************************************************/
void SPI0_NBytesTxRx(uint32_t N_Bytes)
{
	uint32_t  wSPI_Send_Pointer = 0;
	uint32_t  wSPI_Get_Pointer = 0;

	while(wSPI_Send_Pointer != N_Bytes)
	{
		__SPI0_CLR_SEL0;																			//SEL is low
		SN_SPI0->DATA = hwSPI_Tx_Fifo[wSPI_Send_Pointer++];
		while (!(SN_SPI0->STAT & mskSPI_TXFIFOTHF));	//TX Half-Empty
		if(!(SN_SPI0->STAT & mskSPI_RX_EMPTY))								//Check having any data in RXFIFO
		{	
			hwSPI_Rx_Fifo[wSPI_Get_Pointer++] = SN_SPI0->DATA;
		}
	}	

	while(1)
	{
		while(SN_SPI0->STAT & mskSPI_RX_EMPTY); //Get all remaining data
		hwSPI_Rx_Fifo[wSPI_Get_Pointer++] = SN_SPI0->DATA;

		if(wSPI_Get_Pointer == N_Bytes)
		{
			break;
		}
	}
	while(SN_SPI0->STAT & mskSPI_BUSY);

	__SPI0_SET_SEL0;										//SEL is high
	__SPI0_FIFO_RESET;
}


/*****************************************************************************
* Function		: NotPinOut_GPIO_init
* Description	: Set the status of the GPIO which are NOT pin-out to input pull-up. 
* Input				: None
* Output			: None
* Return			: None
* Note				: 1. User SHALL define PKG on demand.
*****************************************************************************/
void	NotPinOut_GPIO_init(void)
{
	//(SN32F248C, SN32F247C, SN32F246C, SN32F2451C) 
#if (PKG == SN32F248C)
	//set P3.2~P3.4 to input pull-up
	SN_GPIO3->CFG = 0x00AAA80A;
#elif (PKG == SN32F247C)	
	//set P0.8~P0.9, P0.12~P0.15 to input pull-up
	SN_GPIO0->CFG = 0x00A0AAAA;
	//set P1.0~P1.2, P1.14~P1.15 to input pull-up
	SN_GPIO1->CFG = 0x0AAAAA80;
	//set P2.12~P2.14 to input pull-up
	SN_GPIO2->CFG = 0x80AAAAAA;
	//set P3.0~P3.4 to input pull-up
	SN_GPIO3->CFG = 0x00AAA800;
#elif (PKG == SN32F246C)
	//set P0.8~P0.9, P0.12~P0.15 to input pull-up
	SN_GPIO0->CFG = 0x00A0AAAA;
	//set P1.0~P1.2, P1.14~P1.15 to input pull-up
	SN_GPIO1->CFG = 0x0AAAAA80;
	//set P2.10~P2.14 to input pull-up
	SN_GPIO2->CFG = 0x800AAAAA;
	//set P3.0~P3.4 to input pull-up
	SN_GPIO3->CFG = 0x00AAA800;
#elif (PKG == SN32F2451C)
	//set P0.0~P0.1, P0.8~P0.15 to input pull-up
	SN_GPIO0->CFG = 0x0000AAA0;
	//set P1.0~P1.4, P1.12~P1.15 to input pull-up
	SN_GPIO1->CFG = 0x00AAA800;
	//set P2.6~P2.15 to input pull-up
	SN_GPIO2->CFG = 0x00000AAA;
	//set P3.0~P3.4, P3.10~P3.11 to input pull-up
	SN_GPIO3->CFG = 0x000AA800;
#endif
}


/*****************************************************************************
* Function		: HardFault_Handler
* Description	: ISR of Hard fault interrupt
* Input			: None
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
__irq void HardFault_Handler(void)
{
	NVIC_SystemReset();
}

