/***********************************************************************
 * Copyright (c)  2017 - 2022, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : spi1_slave.c
 * Description : spi1 slave source file
 * Author(s)   : Mason
 * version     : V1.0
 * Modify date : 2022-08-04
 ***********************************************************************/
#include "spi1_slave.h"


void (*spi1func)(void) = { 0 };

/************************************************************************
 * Function     : SPI1_IRQHandler
 * Description  : SPI1_IRQHandler
 * Input        : none
 * Return       : none
 ************************************************************************/
void SPI1_IRQHandler(void)
{
	if(REG_SPI1_SPIIF & (0x01 << 0))		                            //接收缓存溢出中断标志
	{
		if(spi1func != NULL)
		{	
			((void(*)())(spi1func))(); 
			REG_SPI1_SPIIF = 0x10;					                    //清接收缓存溢出中断
		}
	}
	else
	{
		REG_SPI1_SPIIF = 0x18;						                    //清发送、接收缓存溢出中断
	}  
	     						
}

/************************************************************************
 * Function     : spi1_init
 * Description  : spi1_init
 * Input        : uint8_t work_mode: select spi1 work mode  0,1,2,3
 * Return       : none
 ************************************************************************/
void spi1_init(uint8_t work_mode)       
{
	REG_SCU_PERICLKEN |= (1<<21);										//spi1模块时钟使能
	REG_SCU_PERIRESET |= (1<<21);										//spi1模块正常工作

	REG_SCU_IOCTRLPROTECT = 0xA5A55A5A; 								//清除IO写保护

    REG_SCU_PFSEL = (REG_SCU_PFSEL&(~(0xF<<16)))|(0xC<<16);	            //PF4复用为SPI1_SCK
    REG_SCU_PADIE1 |= (1<<12);                                          //PF4输入使能
    REG_SCU_PFSEL = (REG_SCU_PFSEL&(~(0xF<<24)))|(0xC<<24);	            //PF6复用为SPI1_MOSI
    REG_SCU_PADIE1 |= (1<<14);                                          //PF6输入使能
    REG_SCU_PFSEL = (REG_SCU_PFSEL&(~(0xF<<20)))|(0xA<<20);	            //PF5复用为SPI1_MISO			
    REG_SCU_PFSEL = (REG_SCU_PFSEL&(~(0xF<<12)))|(0xA<<12);	            //PF3复用为SPI1_CSN0
    
	REG_SCU_IOCTRLPROTECT = 0xFFFFFFFF; 								//开启IO写保护
	REG_SPI1_SPICS0 = 0x00;	
	REG_SPI1_SPICS0 |= work_mode;
	
    REG_SPI1_SPICR = 0x00;			                                    //初始化spi1配置寄存器
	REG_SPI1_SPICR &= ~(1<<5);		                                    //从机模式
                                    
	REG_SPI1_SPIIE = 0x00;			                                    //默认状态下关闭所有中断功能
	REG_SPI1_SPIOPCR = 0x0F; 		                                    //开始传输时，先清空内部所有缓存
                                        
	REG_SPI1_SPICR |= (1<<0);	 	                                    //使能spi1
}


/************************************************************************
 * Function     : spi1_irq_init
 * Description  : spi1 irq init
 * Input        : uint8_t irq_enable: irq enable or disable
 *                uint32_t spi1_intr：spi1 interrupt type
 *                void (*pfunc)()：spi1 interrupt callback function
 * Return       : none
 ************************************************************************/
void spi1_irq_init(uint8_t irq_enable,uint32_t spi1_intr,void (*pfunc)())
{
	if(irq_enable == SPI1_IRQ_ENABLE)
	{
		spi1func = pfunc;
		
		NVIC_ClearPendingIRQ(SPI1_IRQn); 
		NVIC_EnableIRQ(SPI1_IRQn);
		
		REG_SPI1_SPIIE |= (1<<spi1_intr);     					        //中断使能	
	}
	else
	{
		REG_SPI1_SPIIE &= ~(0xFF<<0);     							    //中断关闭
		
		spi1func = NULL;
	}
}

/************************************************************************
 * Function     : spi1_irq_receive_byte
 * Description  : receive a byte in interrupt
 * Input        : none
 * Return       : spi rx buff
 ************************************************************************/
uint8_t spi1_irq_receive_byte(void)
{
	return REG_SPI1_SPIRXBUF;				//返回读取寄存器的值
}


#ifdef FULL_DUPLEX_MODE							//全双工传输
/************************************************************************
 * Function     : spi1_slave_full_duplex_tranfer
 * Description  : spi1_slave_full_duplex_tranfer spi1全双工传输
 * Input        : uint8_t *send_data：tx data buff
 *                uint8_t *rec_buff：rx data buff
 *                uint32_t length：data length
 * Return       : 正常发送返回	：0
 *                异常发送返回 	：1
 ************************************************************************/
uint8_t spi1_slave_full_duplex_tranfer(uint8_t *send_data, uint8_t *rec_buff, uint32_t length)
{
	while(length--)
	{
		while(!(REG_SPI1_SPIIF & (1<<SPIIF_TNF)));		                //等待tx Fifo未满

		REG_SPI1_SPITXBUF = *send_data++;				                //写入数据寄存器，把要写入的数据写入发送缓存	
		
		while(!(REG_SPI1_SPIIF & (1<<SPIIF_RXBF)));		                //等待接收缓存非空

		*rec_buff++ = REG_SPI1_SPIRXBUF;	
	}
	return 0;
}

#else					                                                //半双工传输
/************************************************************************
 * Function     : spi1_slave_half_duplex_send_bytes
 * Description  : spi1_slave_half_duplex_send_bytes
 * Input        : uint8_t *buff：tx data buff
 *                uint32_t length：data length
 * Return       : 正常发送返回	：0
 *                异常发送返回 	：1
 ************************************************************************/
uint8_t spi1_slave_half_duplex_send_bytes(uint8_t *buff, uint32_t length)
{
#ifndef SPI_RX_INT_MODE
	REG_SPI1_SPICR |= (1 << 8);							                //打开TXONLY
#endif              
	while(length--)             
	{		                
		while(!(REG_SPI1_SPIIF & (1<<SPIIF_TNF)));		                //等待tx Fifo未满
                
		REG_SPI1_SPITXBUF = *buff++;                
                        
	}               
                    
	while(!(REG_SPI1_SPIIF & (1<<SPIIF_IDLE)));			                //等待发送空闲
                    
    REG_SPI1_SPICR &= ~(1 << 8);						                //关闭TXONLY
    
	return 0;
}

/************************************************************************
 * Function     : spi1_slave_half_duplex_receive_bytes
 * Description  : spi1_slave_half_duplex_receive_bytes 	接收多个byte数据
 * Input        : uint8_t *buff：rx data buff
 *                uint32_t length：data length
 * Return       : 正常发送返回	：0
 *                异常发送返回 	：1
 ************************************************************************/
uint8_t spi1_slave_half_duplex_receive_bytes(uint8_t *buff, uint32_t length)
{
	while(length--)
	{
		while(!(REG_SPI1_SPIIF & (1<<SPIIF_RXBF)));                     //等待接收缓存非空，RXBF事件
                
		*buff++ =  REG_SPI1_SPIRXBUF;					                //返回读取寄存器的值
	}	
	return 0;
}

#endif
/************************************************************************
 * Function     : spi1_wait_idle
 * Description  : spi1_wait_idle 等待SPI0空闲
 * Input        : none
 * Return       : none
 ************************************************************************/
void spi1_wait_idle(void)
{
	while(!(REG_SPI1_SPIIF & (1<<SPIIF_IDLE)));					//等待发送完成
}
