/******************** (C) COPYRIGHT 2019 SONiX *******************************
* COMPANY:		SONiX
* DATE:				2019/05
* AUTHOR:			SA1
* IC:					SN32F760/750
*____________________________________________________________________________
*	REVISION	Date				User		Description
*	1.0				2013/12/17	SA1			1. First release
*	1.2				2014/02/27	SA1			1. Update I2S functions.
*	2.0				2015/05/29	SA1			1. Compatible to CMSIS DFP Architecture in Keil MDK v5.X (http://www.keil.com/dd2/pack/)
*																2. Run HexConvert to generate bin file and show checksum after building.
*	3.0				2018/02/02	SA1			1. Add NotPinOut_GPIO_init to set the status of the GPIO which are NOT pin-out to input pull-up.
*																2. Add SN32F760_CodeOption.s to modify Code option, please modify with Configuration Wizard, 
*																	 and Strongly recommend to keep CS0 for debugging with SN-LINK.
*	3.1				2018/10/05	SA1			1. Remove CodeOption_SN32F760.s, please contact SONiX FAE if needed.
*	3.3				2019/05/31	SA1			1. Fix I2S_Master_Init and I2S_Slave_Init in I2S.c
*____________________________________________________________________________
* 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 <SN32F760.h>
#include <SN32F700_Def.h>
#include ".\Interface\I2S\I2S.h"


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


void I2S_Master_Irq(void);
void I2S_Slave_Irq(void);

uint32_t wI2S_Rx_Check = 0x00A00000;
uint32_t wI2S_Tx_Data = 0x00A00000;


/*_____ D E F I N I T I O N S ______________________________________________*/
#ifndef	SN32F769					//Do NOT Remove or Modify!!!
	#error Please install SONiX.SN32F7_DFP.1.4.3.pack or version >= 1.4.3
#endif
#define	PKG						SN32F769				//User SHALL modify the package on demand (SN32F769, SN32F768, SN32F767, SN32F766, SN32F765, SN32F759, SN32F758, SN32F757, SN32F756, SN32F755) 


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


/*_____ F U N C T I O N S __________________________________________________*/

/*****************************************************************************
* Function		: main
* Description	: This is I2s master Tx sample code, we can use this sample code to set I2S master Tx
								data length, channel length, FIFO level and MCLK div, Bitclk div...etc.
								I2S as master transfer data to slave and receive data from slave and compare Rx data
* Input			: None
* Output		: None
* Return		: None
* Note			: Connect DIN and DOUT 
*****************************************************************************/
int	main (void)
{
	//User can configure System Clock with Configuration Wizard in system_SN32F760.c
	SystemInit();
	SystemCoreClockUpdate();

	PFPA_Init();													//User shall set PFPA if used, do NOT remove!!!

	//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
	I2S_Master_Init();
	//I2S_Slave_Init();

	SN_I2S->TXFIFO = (wI2S_Tx_Data++);
	SN_I2S->TXFIFO = (wI2S_Tx_Data++);
	SN_I2S->TXFIFO = (wI2S_Tx_Data++);
	SN_I2S->TXFIFO = (wI2S_Tx_Data++);	

	//I2S interrupt enable
	I2S_Interrupt_Enable();	
	NVIC_ClearPendingIRQ(I2S_IRQn);
	NVIC_EnableIRQ(I2S_IRQn);

	__I2S_START;		//I2S start	

	while (1);			//Pass
}


/*****************************************************************************
* Function		: I2S_IRQHandler
* Description	: I2S as interrupt handler
* Input			: None
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
__irq void I2S_IRQHandler(void)
{
	I2S_Master_Irq();
	//I2S_Slave_Irq();
}


/*****************************************************************************
* Function		: I2S_Master_Irq
* Description	: I2S master irq
* Input			: None
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void I2S_Master_Irq(void)
{
	uint32_t	wI2S_Read_Data;
	uint32_t  wI2S_Loop_Cnt=0;

	if(SN_I2S->RIS & mskI2S_TXFIFOOVIF)					//Tx overflow
	{												
		SN_I2S->IC = mskI2S_TXFIFOOVIC;		
		while(1);
	}
	else if(SN_I2S->RIS & mskI2S_TXFIFOTHIF)		//Tx threshold
	{									
		while(!(SN_I2S->STATUS & mskI2S_TXFIFOFULL))
		{
			SN_I2S->TXFIFO = (wI2S_Tx_Data++);
			if (wI2S_Tx_Data >= 0x00FFFFFF )		
			wI2S_Tx_Data = 0x00A00000;
		}	
		SN_I2S->IC = mskI2S_TXFIFOTHIC;		
	}
	else if(SN_I2S->RIS & mskI2S_RXFIFOUDIF)		//Rx underflow
	{									
		SN_I2S->IC = mskI2S_RXFIFOUDIC;
		while(1);
	}
	else if(SN_I2S->RIS & mskI2S_RXFIFOTHIF)		//Rx THreshold		
	{
		while(!(SN_I2S->STATUS & mskI2S_RXFIFOEMPTY))
		{
			wI2S_Read_Data = SN_I2S->RXFIFO;
 			if(wI2S_Read_Data != wI2S_Rx_Check)
			{
   			while(1);															//data compare error
			}
			wI2S_Rx_Check++;
			if(wI2S_Rx_Check >= 0x00FFFFFF)
			{
				wI2S_Loop_Cnt++;
				wI2S_Rx_Check = 0x00A00000;
			}
		}
		SN_I2S->IC = mskI2S_RXFIFOTHIC;
	}
}

/*****************************************************************************
* Function		: I2S_Slave_Irq
* Description	: I2S slave irq
* Input			: None
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void I2S_Slave_Irq(void)
{
	uint32_t	wI2S_Read_Data;
	uint32_t  wI2S_Loop_Cnt=0;

	if(SN_I2S->RIS & mskI2S_TXFIFOOVIF)					//Tx overflow	
	{											
		SN_I2S->IC = mskI2S_TXFIFOOVIC;
		while(1);
	}
	else if(SN_I2S->RIS & mskI2S_TXFIFOTHIF)		//Tx threshold
	{								
		while(!(SN_I2S->STATUS & mskI2S_TXFIFOFULL))
		{
			SN_I2S->TXFIFO = (wI2S_Tx_Data++);
			if(wI2S_Tx_Data >= 0x00FFFFFF)
			{
				wI2S_Tx_Data=0x00A00000;
			}
		}
		SN_I2S->IC = mskI2S_TXFIFOTHIC;		
	}
	else if(SN_I2S->RIS & mskI2S_RXFIFOUDIF)		//Rx underflow
	{
		SN_I2S->IC = mskI2S_RXFIFOUDIC;
		while(1);
	}
	else if(SN_I2S->RIS & mskI2S_RXFIFOTHIF)		//Rx THreshold
	{
		while(!(SN_I2S->STATUS & mskI2S_RXFIFOEMPTY))
		{
			wI2S_Read_Data = SN_I2S->RXFIFO;
			if(wI2S_Read_Data != wI2S_Rx_Check)
			{
				while(1);															//data compare error
			}
			wI2S_Rx_Check++;
			if(wI2S_Rx_Check >= 0x00FFFFFF)
			{
				wI2S_Loop_Cnt++;
				wI2S_Rx_Check = 0x00A00000;
			}
		}
		SN_I2S->IC = mskI2S_RXFIFOTHIC;
	}
}

/*****************************************************************************
* 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)
{
#if (PKG == SN32F768) || (PKG == SN32F758)
	//set P0.10~P0.13 to input pull-up
	SN_GPIO0->CFG = 0xA00AAAAA;
	//set P2.7~P2.9 to input pull-up
	SN_GPIO2->CFG = 0xAAA02AAA;
#elif (PKG == SN32F767) || (PKG == SN32F757)
	//set P0.6~P0.7, P0.10~P0.15 to input pull-up
	SN_GPIO0->CFG = 0x000A0AAA;
	//set P1.5, P1.8~P1.9, P1.14~P1.15 to input pull-up
	SN_GPIO1->CFG = 0x0AA0A2AA;
	//set P2.8~P2.13 to input pull-up
	SN_GPIO2->CFG = 0xA000AAAA;
	//set P3.4, P3.7~P3.8 to input pull-up
	SN_GPIO3->CFG = 0xAAA828AA;
#elif (PKG == SN32F766) || (PKG == SN32F756)
	//set P0.5~P0.7, P0.10~P0.15 to input pull-up
	SN_GPIO0->CFG = 0x000A02AA;
	//set P1.5, P1.8~P1.9, P1.14~P1.15 to input pull-up
	SN_GPIO1->CFG = 0x0AA0A2AA;
	//set P2.7~P2.13 to input pull-up
	SN_GPIO2->CFG = 0xA0002AAA;
	//set P3.6~P3.8 to input pull-up
	SN_GPIO3->CFG = 0xAAA80AAA;
#elif (PKG == SN32F765) || (PKG == SN32F755)
	//set P0.3~P0.7, P0.10~P0.15 to input pull-up
	SN_GPIO0->CFG = 0x000A002A;
	//set P1.3~P1.9, P1.12~P1.15 to input pull-up
	SN_GPIO1->CFG = 0x00A0002A;
	//set P2.3~P2.6, P2.8~P2.13 to input pull-up
	SN_GPIO2->CFG = 0xA000802A;
	//set P3.0~P3.1, P3.4~P3.5, P3.7~P3.8 to input pull-up
	SN_GPIO3->CFG = 0xAAA820A0;
#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();
}

