/*
 * SPI_Driv.c
 *
 *  Created on: 2021年4月2日
 *      Author: dell
 */

#include "SPI_Driv.h"

XGpioPs psGpioInstancePtr;     //端口
XGpioPs_Config* GpioConfigPtr; //设备ID


extern u32 K7_U0[16];
extern u32 molex_4_bank_3[4];
extern u32 cs_en_bank_3[4];

/******************************************************************************
* Function    : void interface_initial(u32* device,u32 num_wire)
* Description : interface initial
* Parameter   : device   -- CPLD
* 				num_wire -- 复位线编号
* Return      : void
******************************************************************************/
void interface_initial(u32* device)  //wire_num = cs sck sdi/o
 {
	u32   sck   = *(device+0);
	u32	  cs    = *(device+1);

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);

 }

/******************************************************************************
* Function    : void rst_CPLD(u32* device,u32 num_wire)
* Description : CPLD reset
* Parameter   : device   -- CPLD
* 				num_wire -- 复位线编号
* Return      : void
******************************************************************************/
void rst_CPLD(u32* device,u32 num_wire) //wire_num = cs sck sdi/o
{
	u32	rst_n = *(device+num_wire);

	XGpioPs_WritePin(&psGpioInstancePtr, rst_n, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, rst_n, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, rst_n, 0);
	usleep(2);
	XGpioPs_WritePin(&psGpioInstancePtr, rst_n, 1);
}

/******************************************************************************
* Function    : void spi_write_onewire(char addr, u32 data, char width, u32* device)
* Description : spi onewire write
* Parameter   : addr   -- 地址
* 				data   -- 数据
* 				width  -- 数据长度
* 				device -- CPLD
* Return      : void
******************************************************************************/
void spi_write_onewire(char addr, char *data, char width, u32* device)
{
	char  temp_addr = 0;
	//u32   temp_data = 0;
	u32   temp_data = 0;
	char  i = 0,j=0;
	u32   sck = *(device+0);
	u32	  cs= *(device+1);
	u32   sdi= *(device+2);

	temp_addr = addr;
	///temp_data = data;

	//XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs,  0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs,  0);
	//XGpioPs_WritePin(&psGpioInstancePtr, sdi, 1);			// w/r标志位    1=w 0=r
	//XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	//XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	for(i = 0; i < 8; i++)								// 8bit地址
	{
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

	    if(temp_addr&0x80)
	    	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 1); //sck低电平传输数据     数据从中间变量到通信线上
	    else
	    	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);

	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    temp_addr = temp_addr<<1;                       //sck高电平准备数据,此处为准备第二个数据，第一个数据已经传输完毕
	}

	for(j=0;j<width;j++)
	{
		temp_data = *(data+j);
		for(i = 0; i < 8; i++)                             //nbit数据
		{
			XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
			XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

			if(temp_data&0x80)							//注意数据位nbit，要从[n-1]取位
				XGpioPs_WritePin(&psGpioInstancePtr, sdi, 1);
			else
				XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);

			XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
			XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
			temp_data <<=  1;
		}
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	}

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs , 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);
}

/******************************************************************************
* Function    : u32	spi_read_onewire(char addr, char width, u32* device)
* Description : spi onewire read
* Parameter   : addr   -- 地址
* 				data   -- 数据
* 				width  -- 数据长度
* 				device -- CPLD
* Return      : void
******************************************************************************/
u32	spi_read_onewire(char addr, char width, u32* device,char* read_data)
{
	char  temp_addr=0;
	u32	  temp_data=0;
	char  i=0,j=0;
	u32   sck = *(device+0);
	u32	  cs= *(device+1);
	u32   sdi= *(device+2);
	u32   sdo= *(device+3);

	temp_addr = addr;

	//XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	//XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);		// w/r标志位    1=w 0=r
	//XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	//XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	for(i = 0; i < 8; i++)								// 8bit地址
	{
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

	    if(temp_addr&0x80)
	    	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 1); //sck低电平传输数据     数据从中间变量到通信线上
	    else
	    	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);

	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    temp_addr = temp_addr<<1;                       //sck高电平准备数据,此处为准备第二个数据，第一个数据已经传输完毕
	}

	for(j=0; j<width; j++)
	{
			for(i = 0; i < 8; i++)                             //nbit数据
			{
				XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
				XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

				temp_data = temp_data << 1;                     //sck低电平准备数据    准备好数位，此时的数据相当于从右边的FPGA移进MCU(先准备好中间变量)

				XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
				XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

				if(XGpioPs_ReadPin(&psGpioInstancePtr,sdo))    //sck高电平接收数据     数据匹配到准备好的数位，等待一起传递到MCU
					temp_data = temp_data| 0x00000001;
				XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
			    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
			}
	}

    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);
	read_data[0] = (u8)(temp_data>>16);
	read_data[1] = (u8)(temp_data>>8);
	read_data[0] = (u8)(temp_data);
	return temp_data;
}

/******************************************************************************
* Function    : void fourwire_write(u8 txdata, u32 sdi0, u32 sdi1, u32 sdi2, u32 sdi3)
* Description : forwire write to reg
* Parameter   : txdata--数据
* 				sdi0,sdi1,sdi2,sdi3--IO
* Return      : void
******************************************************************************/
void fourwire_write(u8 txdata, u32 sdi0, u32 sdi1, u32 sdi2, u32 sdi3)
{
	switch(txdata & 0x0F)
	{
	   case 0x00:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x01:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x02:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x03:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x04:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x05:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x06:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x07:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x08:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x09:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0A:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0B:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0C:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0D:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0E:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0F:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	}
}

/******************************************************************************
* Function    : void spi_write_fourwire(char addr, u16 data, u32* device)
* Description : spi fourwire write
* Parameter   : addr   -- 地址
* 				data   -- 数据
* 				width  -- 数据长度
*  				device -- CPLD
* Return      : void
******************************************************************************/
void spi_write_fourwire(char addr, u16 data, u32* device)
{
	u8    temp_addr = 0;
	u16   temp_data = 0;
	u8	  split_addr[2] = {0};	//将8bit地址拆分，分别给4线传输，
	u8	  split_data[4] = {0};	//16bit数据拆成4个4bit
	u8    i;
	u32   sck   = *(device+0);
	u32	  cs    = *(device+1);
	u32	  sdi0 = *(device+2);
	u32	  sdi1 = *(device+3);
	u32	  sdi2 = *(device+4);
	u32	  sdi3 = *(device+5);

	temp_addr = addr;
	temp_data = data;

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	fourwire_write(0x01,sdi0,sdi1,sdi2,sdi3);     			// w/r标志位    1=w 0=r
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	for(i = 0; i < 2;i++)									// 8bit地址 四根线分两次传输
	{
		split_addr[i] = (temp_addr>>(4*(1-i)))&0x0F;		//sck高电平准备数据		数据从MCU到中间变量上
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

		fourwire_write(split_addr[i],sdi0,sdi1,sdi2,sdi3);	//sck低电平传输数据     数据从中间变量到通信线上

		XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	}
	for(i = 0; i < 4;i++)									//16bit数据  4根线分四次传输
	{
		split_data[i] = (temp_data>>(4*(3-i)))&0x0F;
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

		fourwire_write(split_data[i],sdi0,sdi1,sdi2,sdi3);

		XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	}
    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);
    fourwire_write(0x00,sdi0,sdi1,sdi2,sdi3);
    //usleep(20);
}

/******************************************************************************
* Function    : u16	fourwire_read(u32 sdo0, u32 sdo1, u32 sdo2, u32 sdo3)
* Description : forwire read from reg
* Parameter   : sdo0,sdo1,sdo2,sdo3--IO
* Return      : rxdata--数据
******************************************************************************/
u16	fourwire_read(u32 sdo0, u32 sdo1, u32 sdo2, u32 sdo3)
{
	u32 GPIO_PIN[4];
	u16	rdata[4];
	u16 rxdata = 0;

	GPIO_PIN[0] = sdo0;
	GPIO_PIN[1] = sdo1;
	GPIO_PIN[2] = sdo2;
	GPIO_PIN[3] = sdo3;

	for(u8 i = 0; i < 4 ; i++)
	{
		rdata[i] = XGpioPs_ReadPin(&psGpioInstancePtr,GPIO_PIN[i]);
		//xil_printf("rdata[i] = %x\r\n",rdata[i]);
		rxdata   = ((rdata[i])<<i) + rxdata ;
	}
	return	rxdata;
}

/******************************************************************************
* Function    : void spi_read_fourwire(char addr, u16* rxdata, u32* device)
* Description : spi fourwire read
* Parameter   : addr   -- 地址
* 				rxdata -- 数据
* 				device -- CPLD
* Return      : void
******************************************************************************/
void spi_read_fourwire(char addr, u16* rxdata, u32* device)   //接收数据使用指针传递，方便接收多个
{
	u8    temp_addr = 0;
	u16   temp_data = 0;
	u8	  split_addr[2] = {0};	//将8bit地址拆分，分别给4线传输，
	u16	  split_data[4] = {0};	//16bit数据拆成4个4bit
	u8    i = 0;
	u32   sck   = *(device+0);
	u32	  cs    = *(device+1);
	u32	  sdio0 = *(device+2);
	u32	  sdio1 = *(device+3);
	u32	  sdio2 = *(device+4);
	u32	  sdio3 = *(device+5);

	temp_addr = addr;

	split_addr[0] = (temp_addr >> 4)&0x0F;
	split_addr[1] = (temp_addr)&0x0F;

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	fourwire_write(0x00,sdio0,sdio1,sdio2,sdio3);     			// w/r标志位    1=w 0=r
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	for(i = 0; i < 2; i++)									// 8bit地址 四根线分两次传输
	{
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

		fourwire_write(split_addr[i],sdio0,sdio1,sdio2,sdio3);	//sck低电平传输数据     数据从中间变量到通信线上

		XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	}

	for(i = 0; i < 4; i++)
	{
		XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, *(device+2+i),0);  //input
	}

	for(i = 0; i < 4; i++)									//16bit数据  4根线分四次接收
	{
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

		split_data[i] = fourwire_read(sdio0,sdio1,sdio2,sdio3);	//sck低电平准备数据     数据从通信线到中间变量上

		XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	    temp_data = temp_data<<4;
	    temp_data = temp_data + split_data[i];
		//temp_data = (split_data[i]<<(4*(3-i))) + temp_data;		//sck高电平接收数据     数据从中间变量到MCU上
//	    xil_printf("split_data[i],temp_data = %x,%x\r\n",split_data[i],temp_data);

	}

	for(i = 0; i < 4; i++)
	{
		XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, *(device+2+i),1);  //output
	}

    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    fourwire_write(0x00,sdio0,sdio1,sdio2,sdio3);
	*rxdata = temp_data;
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);//add 2 lines
    //usleep(20);
}

/******************************************************************************
* Function    : void GPIO_dir_set(u32* device,char dir)
* Description : change GPIO direction
* Parameter   : device -- CPLD
* 				dir    -- GPIO_OUT/GPIO_IN
* Return      : void
******************************************************************************/
void GPIO_dir_set_16(u32* device,char dir)
{
	u32   sdio[16] = {0};
	u8    i;

	for(i = 0; i < 16;i++)
	{
		sdio[i] = *(device+i);

		//XGpioPs_SetDirectionPin(&psGpioInstancePtr, sdio[i],1);
		XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, sdio[i],dir);
	}

}

void GPIO_dir_set_cs_enable(u32* device,u8 dir)
{
	u32   sdio[4] = {0};
	u8    i;
	u8    dir_temp = 0;

	for(i = 0; i < 4;i++)
	{
		sdio[i]  = *(device+i);
		dir_temp =  (((dir >> (3-i))) & 0x01);
		XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, sdio[i],dir_temp);
	}
}


void  rst(char *d)
{
	XGpioPs_WritePin(&psGpioInstancePtr, *d, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, *d, 1);
	usleep(20);
	XGpioPs_WritePin(&psGpioInstancePtr, *d, 0);
}


void func_test(void)
{

	XGpioPs_Write(&psGpioInstancePtr, 0x03, 0x12345678);
}
