/**
******************************************************************************************************************************************************************************************
*@file                       cpu_spi.c
*@author         
*@data                       
*@version                    v1.0
*@par Copyright(c):
*
*@par History:
*     version:author,date,desc
*     v1.0   :create this file
*
*******************************************************************************************************************************************************************************************
*/
#include "cpu_spi.h"

/*******************************************************************************
* 函数名   : spi_init.
* 说明     : spi初始化
* 参数     : -spix,    			  SPI0、SPI1
             -spi_init_struct,    SPI初始化参数配置,参考 spi_init_type_def 定义
* 返回值   : None.
* 示例     : spi_init(SPI0, &spi_init_structure);
*******************************************************************************/
void spi_init(spi_type_def* spix, spi_init_type_def* spi_init_struct)
{
	spi_set_master_slave_mode(spix,spi_init_struct->spi_mode);// this need SET first before config spi reg	
	spi_cmd(spix,DISABLE);
	spi_it_config(spix,SPI_IT_All,DISABLE);
	spix->CTRLR0 = (spi_init_struct->spi_direction | \
                            spi_init_struct->spi_cpol | \
                            spi_init_struct->spi_cpha | \
                            spi_init_struct->spi_data_size);	
	spix->BAUDR = spi_init_struct->spi_baud_rate_prescaler;
	spix->SER = spi_init_struct->spi_nss;
	spix->RXFTLR = spi_init_struct->spi_rx_fifo_full_threshold;
	spix->TXFTLR = spi_init_struct->spi_tx_fifo_empty_threshold;
}

/*******************************************************************************
* 函数名   : spi_cmd.
* 说明     : spi使能
* 参数     : -spix,     	SPI0、SPI1
             -new_state,    使能或不使能,参考 functional_state_t 定义
* 返回值   : None.
* 示例     : spi_cmd(SPI0, ENABLE);
*******************************************************************************/
void spi_cmd(spi_type_def* spix, functional_state_t new_state)
{
	if (new_state != DISABLE)
	{
		/* Enable the selected SPI peripheral */
		spix->SSIENR = 1;		//ENABLE current SPI
	}
	else
	{
		/* Disable the selected SPI peripheral */
		spix->SSIENR = 0;		//DISABLE current SPI
	}
}

/*******************************************************************************
* 函数名   : spi_it_config.
* 说明     : spi中断配置
* 参数     : -spix,     	SPI0、SPI1
             -spi_it,     	SPI中断模式
             -new_state,    使能或不使能,参考 functional_state_t 定义
* 返回值   : None.
* 示例     : spi_it_config(SPI0, SPI_IT_RXF, ENABLE);
*******************************************************************************/
void spi_it_config(spi_type_def* spix, uint32_t spi_it, functional_state_t new_state)
{
	uint32_t spi_chn_num = 0;
	switch(get_spi_chn_num(spix))
	{
		case 0:	( SYSCFG->SPI_SLAVE_SEL & 0x01 ) ? ( spi_chn_num = SPI_Mode_Slave ) : ( spi_chn_num = SPI_Mode_Master );
				break;
		case 1:	( SYSCFG->SPI_SLAVE_SEL & 0x02 ) ? ( spi_chn_num = SPI_Mode_Slave ) : ( spi_chn_num = SPI_Mode_Master );
				break;
		case 2: return;
	}
			
    switch (spi_chn_num)
    {
        case SPI_Mode_Slave:         /* SPI Slave Mode */
            /* Return the data in the DR register */
			if(new_state != DISABLE)
				((spi_type_def*)(uint32_t)spix)->IMR |= spi_it;
			else
				((spi_type_def*)(uint32_t)spix)->IMR &= ~spi_it;
            break;
        case SPI_Mode_Master:         /* SPI Master Mode */
            /* Return the data in the DR register */
			if(new_state != DISABLE)
				spix->IMR |= spi_it;
			else
				spix->IMR &= ~spi_it;
            break;
        default:
            break;
    }
}
/*******************************************************************************
* 函数名   : spi_set_master_slave_mode.
* 说明     : 设置spi主从模式
* 参数     : -spix,     	SPI0、SPI1
             -spi_mode,     SPI模式类型，分为主模式、从模式
* 返回值   : None.
* 示例     : spi_set_master_slave_mode(SPI0,SPI_Mode_Master);
*******************************************************************************/
void spi_set_master_slave_mode(spi_type_def* spix,uint32_t spi_mode)
{
	uint32_t tmp_reg = 0;
	if(spix == SPI0)
		tmp_reg = SYSCFG_SPI_SLAVE_SEL_SPI0_SLV_SEL;
	else
		tmp_reg = SYSCFG_SPI_SLAVE_SEL_SPI1_SLV_SEL;
	
	if(spi_mode == SPI_Mode_Master)
		SYSCFG->SPI_SLAVE_SEL &= ~tmp_reg;
	else
		SYSCFG->SPI_SLAVE_SEL |= tmp_reg;
		
}

/*******************************************************************************
* 函数名   : spi_is_rx_not_empty.
* 说明     : spi接收不为空
* 参数     : -spix,     	SPI0、SPI1
* 返回值   : TRUE.			接收FIFO未空
			 FALSE.			接收FIFO空
* 示例     : spi_is_rx_not_empty(SPI0);
*******************************************************************************/
boolean spi_is_rx_not_empty(spi_type_def* spix)
{
	if(spix->SR & SPI_SR_RFNE)
		return TRUE;
	else
		return FALSE;
}

/*******************************************************************************
* 函数名   : spi_is_tx_empty.
* 说明     : spi发送为空
* 参数     : -spix,     	SPI0、SPI1
* 返回值   : TRUE.			发送FIFO空
			 FALSE.			发送FIFO未空
* 示例     : spi_is_tx_empty(SPI0);
*******************************************************************************/
boolean spi_is_tx_empty(spi_type_def* spix)
{
	if(spix->SR & SPI_SR_TFE)
		return TRUE;
	else
		return FALSE;
}

/*******************************************************************************
* 函数名   : spi_send_data.
* 说明     : spi发送数据
* 参数     : -spix,     	SPI0、SPI1
			 -data,			数据
* 返回值   : None.
* 示例     : spi_send_data(SPI0, send_buf);
*******************************************************************************/
void spi_send_data(spi_type_def* spix, uint16_t data)
{
	/* Write in the DR register the data to be sent */
	uint32_t spi_chn_num = 0;
	switch(get_spi_chn_num(spix))
	{
		case 0:	( SYSCFG->SPI_SLAVE_SEL & 0x01 ) ? ( spi_chn_num = SPI_Mode_Slave ) : ( spi_chn_num = SPI_Mode_Master );
				break;
		case 1:	( SYSCFG->SPI_SLAVE_SEL & 0x02 ) ? ( spi_chn_num = SPI_Mode_Slave ) : ( spi_chn_num = SPI_Mode_Master );
				break;
		case 2: return;
	}
		
    switch (spi_chn_num)
    {
        case SPI_Mode_Slave:         /* SPI Slave Mode */
            /* Return the data in the DR register */
            spix->DR = data;
            break;
        case SPI_Mode_Master:         /* SPI Master Mode */
            /* Return the data in the DR register */
            (((spi_type_def*)((uint32_t)spix + 0x0000)))->DR = data;
            break;
        default:
            break;
    }
}

/*******************************************************************************
* 函数名   : spi_receive_data.
* 说明     : spi接收数据
* 参数     : -spix,     	SPI0、SPI1
* 返回值   : None.
* 示例     : spi_receive_data(SPI0);
*******************************************************************************/
uint16_t spi_receive_data(spi_type_def* spix)
{
	/* Return the data in the DR register */
	uint32_t spi_chn_num = 0;
	switch(get_spi_chn_num(spix))
	{
		case 0:	( SYSCFG->SPI_SLAVE_SEL & 0x01 ) ? ( spi_chn_num = SPI_Mode_Slave ) : ( spi_chn_num = SPI_Mode_Master );
				break;
		case 1:	( SYSCFG->SPI_SLAVE_SEL & 0x02 ) ? ( spi_chn_num = SPI_Mode_Slave ) : ( spi_chn_num = SPI_Mode_Master );
				break;
		case 2: return 0;
	}
		
    switch (spi_chn_num)
    {
        case SPI_Mode_Slave:         /* SPI Slave Mode */
            /* Return the data in the DR register */
            return (uint16_t)spix->DR;
        case SPI_Mode_Master:         /* SPI Master Mode */
            /* Return the data in the DR register */
            return (uint16_t)(((spi_type_def*)((uint32_t)spix + 0x0000)))->DR;
        default:
            break;
    }
    return 0;
}

/*******************************************************************************
* 函数名   : spi_get_it_status.
* 说明     : 获取spi中断状态
* 参数     : -spix,     			SPI0、SPI1
			 -spi_it        		SPI中断模式
* 返回值   : bitstatus = SET.    	产生相应中断
			 bitstatus = RESET.     未产生相应中断
* 示例     : spi_get_it_status(SPI0,SPI_IT_TXE));
*******************************************************************************/
itstatus spi_get_it_status(spi_type_def* spix, uint32_t spi_it)
{
	itstatus bitstatus = RESET; 
	if (spix->ISR & spi_it)
	{
			bitstatus = SET;
	}
	else
	{
			bitstatus = RESET;
	}
	return bitstatus;
}

/*******************************************************************************
* 函数名   : spi_clear_it_pending_bit.
* 说明     : 清除spi中断位
* 参数     : -spix,     	SPI0、SPI1
			 -spi_it        SPI中断类型
* 返回值   : None.
* 示例     : spi_clear_it_pending_bit(SPI0,SPI_IT_RXF);
*******************************************************************************/
void spi_clear_it_pending_bit(spi_type_def* spix, uint32_t spi_it)
{
	uint32_t tmp_reg = 0;

	if (SPI_IT_MST | spi_it)
	{
			tmp_reg = spix->MSTICR;
	}
	if (SPI_IT_RXU | spi_it)
	{
			tmp_reg = spix->RXUICR;
	}
	if (SPI_IT_RXO | spi_it)
	{
			tmp_reg = spix->RXOICR;
	}
	if (SPI_IT_TXO | spi_it)
	{
			tmp_reg = spix->TXOICR;
	}
	tmp_reg = tmp_reg;
}


/*******************************************************************************
* 函数名   : get_spi_chn_num.
* 说明     : spi通道选择
* 参数     : -spix,     	SPI0、SPI1
* 返回值   : result = 0.	spix=SPI0
			 result = 1.    spix=SPI1
* 示例     : get_spi_chn_num(SPI0);
*******************************************************************************/
static uint8_t get_spi_chn_num(spi_type_def* spix)
{
    uint8_t result = 0;
    if (spix == SPI0){
        result = 0;
    }else if (spix == SPI1){
        result = 1;
    } 
    return (result);
}

/*******************************************************************************
* 函数名   : spi_get_flag_status.
* 说明     : 获取spi状态
* 参数     : -spix,     	SPI0、SPI1
			 -spi_flag		想要获取的状态
* 返回值   : flag_status.	想要获取状态产生			 
* 示例     : spi_get_flag_status(SPI0,SPI_FLAG_BSY);
*******************************************************************************/
flag_status spi_get_flag_status(spi_type_def* spix, uint32_t spi_flag)
{
    flag_status bitstatus = RESET; 
	uint32_t spi_chn_num = 0;
	switch(get_spi_chn_num(spix))
	{
		case 0:	( SYSCFG->SPI_SLAVE_SEL & 0x01 ) ? ( spi_chn_num = SPI_Mode_Slave ) : ( spi_chn_num = SPI_Mode_Master );
				break;
		case 1:	( SYSCFG->SPI_SLAVE_SEL & 0x02 ) ? ( spi_chn_num = SPI_Mode_Slave ) : ( spi_chn_num = SPI_Mode_Master );
				break;
		case 2: return bitstatus;
	}
		
    switch (spi_chn_num)
    {
        case SPI_Mode_Slave:         /* SPI Slave Mode */
            if ((spix->SR & spi_flag) != RESET)
            {
                bitstatus = SET;
            }
            else
            {
                bitstatus = RESET;
            }
            break;
        case SPI_Mode_Master:        /* SPI Master Mode */
            if (((((spi_type_def*)((uint32_t)spix + 0x0000)))->SR & spi_flag) != RESET)
            {
                bitstatus = SET;
            }
            else
            {
                bitstatus = RESET;
            }
            break;
        default:
            break;
    }
	return bitstatus;
}
